NASM参数长度

3 linux x86 assembly nasm

我正在编写一个简单的程序来显示用户提供的名称.结果是我应该能够输入命令并获得预期的结果.

命令

./hello John
Run Code Online (Sandbox Code Playgroud)

结果

Hello, John.
Run Code Online (Sandbox Code Playgroud)


然而,当程序开始显示名称时,它却没有.我认为它与计算参数的长度有关.请你们看看我的代码并告诉我你的想法?

; hello.asm
;
; Assemble: nasm -f elf hello.asm
; Link:     ld -o hello hello.o
; Run:      ./hello <name>

section .data
    period:      db  ".", 10
    periodLen:   equ $-period

    helloMsg:    db  "Hello, "
    helloMsgLen: equ $-helloMsg

    usageMsg:    db  "Usage: hello <name>", 10
    usageMsgLen: equ $-usageMsg

section .text
    global _start

_start:
    pop eax                     ; Get number of arguments
    cmp eax, 2                  ; If one argument
    jne _help                   ; Not equal, show help + exit

    mov eax, 4                  ; System call to write
    mov ebx, 1                  ; Write to console
    mov ecx, helloMsg           ; Display "Hello, "
    mov edx, helloMsgLen        ; Length of hello message
    int 80h

    mov eax, 4                  ; System call to write
    mov ebx, 1                  ; Write to console
    pop ecx                     ; Get program name
    pop ecx                     ; Get name
    mov edx, $                  ; Beginning of line
    sub edx, ecx                ; Get length of name
    int 80h

    mov eax, 4                  ; System call to write
    mov ebx, 1                  ; Write to console
    mov ecx, period             ; Display a period
    mov edx, periodLen          ; Length of period
    int 80h

    mov eax, 1                  ; System call to exit
    mov ebx, 0                  ; No errors
    int 80h

_help:
    mov eax, 4                  ; System call to write
    mov ebx, 1                  ; Write to console
    mov ecx, usageMsg           ; Display usage message
    mov edx, usageMsgLen        ; Length of usage message
    int 80h

    mov eax, 1                  ; System call to exit
    mov ebx, 0                  ; No errors
    int 80h
Run Code Online (Sandbox Code Playgroud)

Bla*_*ear 5

好的,既然你从未使用过调试器,我会告诉你如何.首先,编译nasm -f elf -g hello.asm.该-g开关有助于调试器,这样您就可以设置断点等.现在开始输入gdb ./hello -q并输入break 34.这告诉gdb在第34行停止.运行程序(输入run emi(emi是我的名字:P)).你应该看到这样的东西:

blackbear@blackbear-laptop:~$ gdb ./hello -q
Reading symbols from /home/blackbear/hello...done.
(gdb) break 34
Breakpoint 1 at 0x80480a9: file hello.asm, line 34.
(gdb) run emi
Starting program: /home/blackbear/hello emi
Hello, 
Breakpoint 1, _start () at hello.asm:34
34      pop ecx                     ; Get name
(gdb) 
Run Code Online (Sandbox Code Playgroud)

好的,让我们看看是什么ecx,输入display (char *) $ecx:

(gdb) display (char *) $ecx
1: (char *) $ecx = 0xbffff63e "/home/blackbear/hello"
Run Code Online (Sandbox Code Playgroud)

您可以使用step一条指令继续:

(gdb) step
35      mov edx, $                  ; Beginning of line
1: (char *) $ecx = 0xbffff654 "emi"
Run Code Online (Sandbox Code Playgroud)

好的,我们在这里.ecx指向我的名字,所以问题不在这里.现在我们不再需要观看ecx,因此使用undisplay gdb将不再显示它.但我们需要检查edx:

(gdb) undisplay
Delete all auto-display expressions? (y or n) y
(gdb) display $edx
2: $edx = 7
(gdb) step
36      sub edx, ecx                ; Get length of name
2: $edx = 134512810
(gdb) step
37      int 80h
2: $edx = 1208257110
Run Code Online (Sandbox Code Playgroud)

嗯,猜你没想到这个,对吗?:)问题似乎在这里:mov edx, $.我不明白$(从未使用过NASM),请你解释一下吗?

编辑
好了.你误解了教程说的内容.它$代表了它的当前位置,实际上:

36      sub edx, ecx                ; Get length of name
11: $edx = 134512810
(gdb) display (void *) $edx
12: (void *) $edx = (void *) 0x80480aa
(gdb) display (void *) $eip
13: (void *) $eip = (void *) 0x80480af
Run Code Online (Sandbox Code Playgroud)

现在edx包含指令的地址mov edx, $.这是5个字节长(操作码(1个字节)+地址(4个字节)),这就是原因eip - edx = 5.
为了获得论证的长度你唯一的方法是使用类似的东西strlen(),但我不能帮助你,NASM不是我的汇编程序.:)