gpt4 book ai didi

linux - NASM 参数长度

转载 作者:可可西里 更新时间:2023-11-01 11:50:41 24 4
gpt4 key购买 nike

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

命令

./hello John

结果

Hello, John.


然而,当程序开始显示名称时,它并没有显示。我相信这与计算参数的长度有关。你们可以看看我的代码并告诉我您的想法吗?

; 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

最佳答案

好的,既然您从未使用过调试器,我将向您展示如何使用。首先,使用 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)

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

(gdb) display (char *) $ecx
1: (char *) $ecx = 0xbffff63e "/home/blackbear/hello"

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

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

好的,我们到了。 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

嗯,我猜你没想到这一点,对吧? :) 问题似乎出在这里: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

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

关于linux - NASM 参数长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5758789/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com