用nasm打印`argv []`

时间:2016-09-07 19:19:35

标签: nasm

我尝试使用nasm:

打印给我程序的命令行参数
GLOBAL main
EXTERN printf

section .rodata
fmt db "Argument: %s", 10, 0

section .text
main:
    push    ebp                 ; push ebp0
    mov     ebp, esp        ; [ebp1] == ebp0

    push    dword[ebp+8]        ; push argc
    call    print_args

    mov     eax, 0      ; return(0)
    mov     esp, ebp    ; pop
    pop     ebp             ; stack frame
    ret

print_args:
    push    ebp             ; pusheo ebp1
    mov     ebp, esp    ; [ebp2] == ebp1
    mov     edi, dword[ebp+8]   ; [ebp+8] == argc
    jmp     lop
postlop:
    mov     esp, ebp
    pop     ebp
    ret


lop:
    sub     edi, 1
    cmp     edi, 0
    jz      postlop
    mov     esi, [ebp] ; [esi] == ebp1
    mov     ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv[0]?
    push    ebx
    push    fmt
    call    printf
    jmp     lop

但是,这只打印垃圾(我相信这应该打印argv[0]argc-1次。)。

我用以下代码编译我的代码:

nasm -f elf32 main.asm
gcc -m32 main.o -o main.out

有什么问题?

顺便说一句,使用 dword[ebp+8] 可以正常使用 argc

我在ubuntu上运行它。程序会输出Argument: ... argc-1次,但...是垃圾。

2 个答案:

答案 0 :(得分:2)

就像[epb+8]argc[esi + 12]argv 数组的地址论证地址。因此,为了找到argv[0],您必须再次取消引用。

mov     esi, [ebp]      ; [esi] == ebp1
mov     ebx, [esi + 12] ; [esi+12] = [ebp1+12] = argv
push    dword [ebx]     ; [ebx] = argv[0]
       ;^^^^^^^^^^^
push    fmt
call    printf

答案 1 :(得分:0)

我已经完成了,这就是您所需要的

如此组装。在我的32位Debian 9 VM上:

$ nasm -felf32 -g args.s -o args.o
$ gcc -no-pie args.o -o args


        segment .data
format  db      "%s",0x0a,0
        segment .text
        global  main            ; let the linker know about main
        extern  printf          ; resolve printf from libc
main:
        push    ebp             ; prepare stack frame for main
        mov     ebp, esp
        sub     esp, 8
        mov     edi, dword[ebp+8]    ; get argc into edi
        mov     esi, dword[ebp+12]   ; get first argv string into esi
start_loop:
        xor     eax, eax
        push    dword [esi]     ; must dereference esi; points to argv
        push    format
        call    printf
        add     esi, 4          ; advance to the next pointer in argv
        dec     edi             ; decrement edi from argc to 0
        cmp     edi, 0          ; when it hits 0, we're done
        jnz     start_loop      ; end with NULL pointer
end_loop:
        xor     eax, eax
        leave
        ret