2017-03-18 27 views
0

我正在学习Docker for Mac上的Ubuntu 16.10上的x86_64 NASM程序集。如何在NASM中正确比较命令行参数的数量?

以下程序需要两个命令行参数,并对它们进行求和。
如果命令行参数的数量不是两个,则显示错误消息(跳转到argcError)。

当我执行这个程序时,它跳转到argcError节,尽管传递给两个命令行参数。

为什么这个程序跳转到argError

section .data 
    SYS_WRITE equ 1 
    STD_IN equ 1 
    SYS_EXIT equ 60 
    EXIT_CODE equ 0 

    NEW_LINE db 0xa 
    WRONG_ARGC db "Must be two command line arguments", 0xa 

section .text 
    global _start 

_start: 
    pop rcx 
    cmp rcx, 3 
    jne argcError 
    add rsp, 8 
    pop rsi 
    call str_to_int 

    mov r10, rax 
    pop rsi 
    call str_to_int 
    mov r11, rax 
    add r10, r11 




argcError: 
    mov rax, 1 
    mov rdi, 1 
    mov rsi, WRONG_ARGC 
    mov rdx, 35 
    syscall 
    jmp exit 


str_to_int: 
    xor rax, rax 
    mov rcx, 10 
next: 
    cmp [rsi], byte 0 
    je return_str 
    mov bl, [rsi] 
    sub bl, 48 
    mul rcx ; rax = rax * rcx 
    add rax, rbx 
    inc rsi 
    jmp next 

return_str: 
    ret 

int_to_str: 
    mov rdx, 0 
    mov rbx, 10 
    div rbx 
    add rdx, 48 
    add rdx, 0x0 
    push rdx 
    inc r12 
    cmp rax, 0x0 
    jne int_to_str 
    jmp print 


print: 
    ; calculate byte length of number string 
    mov rax, 1 
    mul r12 
    mov r12, 8 
    mul r12 
    mov rdx, rax 
    ; print sum 
    mov rax, SYS_WRITE 
    mov rdi, STD_IN 
    mov rsi, rsp 
    syscall 

    jmp printNewline 

printNewline: 
    mov rax, SYS_WRITE 
    mov rdi, STD_IN 
    mov rsi, NEW_LINE 
    mov rdx, 1 
    syscall 
    jmp exit 

exit: 
    mov rax, SYS_EXIT 
    mov rdi, EXIT_CODE 
    syscall 
+3

在'_start'你'电话str_to_int MOV R11,RAX 加入R10,r11'然后你继续在argcError执行的代码。我想你想在'add r10,r11'后面跳到出口标签。您是否尝试过使用像GDB这样的调试器来完成这项工作? –

回答

0

Micheal Petch指出您的代码中可能存在其他错误,但是您初始化RSI的方式不正确。是的,ESP确实指出了传递的参数的数量,但是将它从堆栈中弹出然后再次向ESP添加8在功能上也是等同的。

mov  rcx, [rsp] 

然后通过弹入RSI它只成为一个RCX的副本。如果你想这样做,它应该是这样的

pop  rcx 
....... 
add  rsp, 24    ; Now RSP is pointing to proper place in array of pointers 
pop  rsi 
add  rsp, 16    ; Now point to pointer to second argument 
pop  rsi 

另一种方法是唯一的,因为我个人的偏好是不使用堆栈指针的时间比其预期其他在下一个例子。

mov  rsi, rsp 
lodsq       ; Read # of arguments passed by OS 
add  rsi, 8     ; bounce over application name 
cmp  al, 3 
jnz  argError 
push rsi 
lodsq 
mov  rsi, rax    ; RSI points to first agument 
call Convert 
pop  rsi 
lodsq 
mov  rsi, rax 
call Convert