2

我正在尝试读取传递给我的可执行文件的文件名并使用程序集写入该文件。它编译没有错误,但执行时失败。我的代码到底有什么问题?

BITS 32
segment .data
text db "text"

segment .text

global main

main:
pop ebx 
pop ebx
pop ebx    ; pop pointer to filename into ebx
mov eax,0x5  ;syscall open
mov ecx,0x2   ;flag read/write
int 0x80   ;call kernel
mov ebx,eax   ;save returned file descriptor
mov eax,0x4 ; write syscall
mov ecx,text ;mov pointer to text into ecx
mov edx,0x4 ;string length
int 0x80  ;exit syscall
mov eax,0x1
int 0x80
4

2 回答 2

5

由于您是从 libc 调用的,因此您还必须记住您有返回地址,以便您可以返回那里。如果您只有一个简单的汇编程序(就像很多教程一样!),这与您得到的不同。考虑到这一点:

pop ebx    ;; pops return address to libc caller (_start usually)
pop ebx    ;; pops argc
pop ebx    ;; pops argv !!WAS!!: ; pop pointer to filename into ebx

这是打印第一个参数的方法。您应该可以从那里开始(注意:我可能犯了错误):

    BITS 32

    section .text
    global main
    extern strlen

main:
    pop ecx ; Return address
    pop ecx ; argc
    pop ecx ; argv 
    mov ecx, [ecx+4] ; argv[1]

    push ecx
    call strlen
    mov edx, eax ; count
    pop ecx ; buf

    mov eax, 4 ; sys_write
    mov ebx, 1 ; stdout
    int 0x80

    mov eax, 1 ; sys_exit
    mov ebx, 0 ; status
    int 0x80
于 2011-10-21T20:44:37.413 回答
2

在进入 main 时:堆栈具有以下内容:

...
*envp[]
*argv[]
argc
return address

当你pop ebx三次,你最终访问argv而不是 argv[1]

argv是指向以 NULL 结尾的数组的指针char *,因此您必须遵循间接寻址,如@user786653 所示。

于 2011-10-21T20:47:02.220 回答