|
CS456 - Systems Programming
| Displaying exercises/e4/solution/bitcount.s
; Syscall numbers are defined in /usr/include/asm/unistd_64.h:
%define SYS_READ 0
%define SYS_WRITE 1
%define SYS_OPEN 2
%define SYS_CLOSE 3
%define SYS_EXIT 60
%define STDIN_FILENO 0
%define STDOUT_FILENO 1
%define STDERR_FILENO 2
SECTION .data
usage1: db`Usage: `,0
usage2: db` <int>\n`,0
nl: db`\n`,0
SECTION .bss
numbuf: resb 32
SECTION .text
; Prints the string pointed to by rsi:
puts:
mov rdx, 0
.loop: cmp BYTE [rsi+rdx], `\0` ; rdx = strlen(rsi);
je .stop
inc rdx
jmp .loop
.stop: mov rax, SYS_WRITE ; write(STDOUT_FILENO, rsi, rdx)
mov rdi, STDOUT_FILENO
syscall
ret
; Print the number in the rax register
printnum:
lea rsi, [numbuf+32]
mov BYTE [rsi], 0
mov rbx, 10 ; rbx = 10 (the base for our numbers)
mov r12, 0 ; r12 = false (negative flag)
cmp rax, 0
jge .loop ; if (rax >= 0) goto .loop
neg rax ; rax = -rax;
mov r12, 1 ; r12 = true (number is negative)
.loop: ; do {
cqo
div rbx ; rax = rax/rbx; rdx = rax%rbx;
add dl, '0' ; rax += '0';
dec rsi ; rsi--;
mov BYTE [rsi], dl ; *rsi = dl;
cmp rax, 0
jne .loop ; } while (rax > 0)
cmp r12, 1 ; if (r12 == 1) {
jne .skipneg
dec rsi ; *(--rsi) = '-';
mov BYTE [rsi], '-' ; }
.skipneg:
call puts ; puts(rsi);
ret
; convert the string pointed at by rsi to a integer in rax;
myatoi: ;int64_t myatoi(char *rsi)
mov rax, 0 ; rax = 0; // number to be computed
mov r11, 0 ; r11 = 0; // negative flag
mov r12, 0 ; r12 = 0; // temporary variable
mov rbx, 10 ; rbx = 10; // base to multiply by
cmp BYTE [rsi], '-' ; if (*s == '-') {
jne .loop
mov r11, 1 ; neg = 1;
inc rsi ; rsi++
.loop: ; while (isdigit(*s)) {
cmp BYTE [rsi], '0'
jl .exit
cmp BYTE [rsi], '9'
jg .exit
mul rbx ; rax = rax * 10;
mov r12b, BYTE [rsi] ; r12 = *rsi;
sub r12, '0' ; r12 = r12 - '0';
add rax, r12 ; rax = rax + r12;
inc rsi ; rsi++
jmp .loop ; }
.exit:
cmp r11, 1 ; if (r11)
jne .skip
neg rax ; rax = -rax;
.skip:
ret ; return rax;
global _start
_start: ; int main(int argc, char **argv)
MOV r15, 0 ; int64_t r15 = 0;
MOV r14, 0 ; int r14 = 0;
CMP QWORD [rsp], 2 ; if (argc < 2) {
JGE .continue
MOV rsi, usage1
call puts ; puts("Usage: ");
MOV rsi, [rsp+8]
call puts ; puts(argv[0]);
MOV rsi, usage2
call puts ; puts(" <int>\n");
MOV rdi, 1
JMP .exit ; exit(1);
; }
.continue:
MOV rsi, [rsp+16] ; rsi = argv[1];
call myatoi ; r15 = myatoi(rsi);
MOV rcx, 0 ; rcx = 0; // bit-count
.loop: ; do {
TEST rax, 1 ; if (rax & 1)
JZ .skip
INC rcx ; rcx++;
.skip:
SHR rax, 1 ; rax >>= 1;
JNE .loop ; } while (rax);
MOV rax, rcx
call printnum ; printnum(rcx);
MOV rsi, nl
call puts ; puts("\n");
MOV rdi, 0 ; exit(0);
.exit:
MOV rax, 60
syscall
|