linux nasm命令行args为整数

时间:2012-03-29 18:43:14

标签: linux assembly nasm

我几天来一直试图解决这个问题,最后在这里张贴了一些帮助。这个练习对我来说纯粹是学术性的,但它已经到了我只是需要来理解为什么这不起作用或我做错了。

section .text
    global _start

_start:
    pop eax
    pop ebx
    pop ecx

_exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

编译/链接:

$ nasm -f elf -o test.o test.asm
$ gcc -o test test.o

在参数为“5”的gdb中运行它:

$ gdb test
...
(gdb) b _exit
Breakpoint 1 at 0x8048063
(gdb) r 5
Starting program: /home/rich/asm/test 5

Breakpoint 1, 0x08048063 in _exit ()
(gdb) i r
eax            0x2      2
ebx            0xbffff8b0       -1073743696
ecx            0xbffff8c8       -1073743672
edx            0x0      0
esp            0xbffff78c       0xbffff78c
ebp            0x0      0x0
...

所以eax在这里有意义 - 它是0x2,或2,argc。我的问题是:如何将值“5”(或0x5)放入寄存器?据我了解,ecx是指向我的值5的指针,那么如何将其“取消引用”为可用的数字,即我可以做算术的数字呢?

2 个答案:

答案 0 :(得分:2)

你想用它做什么?您的理解是正确的:内核将argc计数推送到堆栈的顶部,在其下面是argv [0] ... argv [argc-1]以相反的顺序(即堆栈顶部/最低内存地址保持第一个)参数)。您可以使用gdb对系统上的任何二进制文件进行检查:

$ echo "int main(){return 0;}" > test.c
$ gcc test.c
$ gdb ./a.out
(gdb) b _start
(gdb) r A B C D E
(gdb) p ((void**)$rsp)[0]
$2 = (void *) 0x6
(gdb) p (char*)((void**)$rsp)[1]
$4 = 0x7fffffffeab7 "/home/andy/a.out"
(gdb) p (char*)((void**)$rsp)[2]
$5 = 0x7fffffffeac8 "A"
(gdb) p (char*)((void**)$rsp)[3]
$6 = 0x7fffffffeaca "B"
(gdb) p (char*)((void**)$rsp)[4]
$7 = 0x7fffffffeacc "C"
(gdb) p (char*)((void**)$rsp)[5]
$8 = 0x7fffffffeace "D"
(gdb) p (char*)((void**)$rsp)[6]
$9 = 0x7fffffffead0 "E"

你是否可能会问如何解析字符串?这是一个更复杂的问题。

答案 1 :(得分:1)

我意识到这可能有点晚了你可能已经解决了这个问题或者转向其他事情,但我在搜索相关内容时遇到了这个问题,并认为我可以帮助其他任何遇到这个问题的人。

我认为你在这里遇到的问题是你传递给你的程序的“5”然后不会像你想象的那样存储为整数5。该参数作为char传递给您的程序,因此Andy指出您将有一个指向包含0x35的字节的指针 - 这是表示ASCII字符5的整数值 - 而不是指向整数值5的指针。

要将您的参数用作整数,您需要将字节转换为ASCII表定义的等效整数 - 否则您会发现传入char 5,但是您尝试使用此算法进行的任何数学运算都将使用53(0x35)因为它代表ASCII中的5。

您可以在示例asm program here的rsi_to_bin函数中找到如何执行该转换的示例。一旦你将ascii代码转换为它的实际整数等价,你将获得传入的正确数字,并且能够用它执行你想要的任何算术。一个非常简单的例子就是从输入中减去48 - 假设你只传入0-9的单个整数,那就可以了。