打印命令行参数 x86 程序集

Printing Commandline Arguments x86 Assembly

首先,我是汇编新手,但在 C++ 方面有不错的背景。我的问题源于我关注的关于 Commandline arguments using assembly.

的教程

当程序处于 运行 时,它会根据教程执行它应该执行的所有操作,即显示程序输入列表: ./asm1 arg1 arg2 arg3

问题在于您提供星号作为参数时: ./asm1 *

It effectively does a /usr/bin/ls on the CWD.

我的问题是如何防止这种情况,以及有关实施该计划的更好方法的任何建议。

Replaced:

; the loop
        cmp ecx, eax        ; if ecx not equal to eax
        jne begin_for_loop  ; jmp to loop, else exit

With:

; the loop
         cmp ecx, eax        ; if ecx not equal to eax
         jmp begin_for_loop  ; jmp to loop, else exit

And I found a bigger issue where the program prints ENV variables to the screen.

原程序如下:

; FOR LOOP: Print commandline arguments> an equivalent program to 
this in assembly
SECTION .data

    argv db "Arguments = %s",10,0
    argc db "Argument Count = %d",10,0

SECTION .text
; allow access to printf
extern printf
; make main_function available externally
global main


main:    ; int main (int argc, char* argv[])
    push ebp
    mov ebp,esp
    sub esp, 10

    mov eax, DWORD [ebp + 8]    ; points to argc
    mov ebx, DWORD [ebp + 12]   ; points to argv
    mov ecx, 0      ; mov ZERO to count register

begin_for_loop:
    ; always preserve values prior to external function calls
    ; external function calls may modify values you placed in registers
    push ebx    ; preserve ebx; holds argument address
    push eax    ; preserve eax; holds number of arguments
    push ecx    ; preserve ecx; holds the counter

    ; call printf
    push DWORD [ebx]
    push argv
    call printf
    add esp, 8  ; clean up the stack

    ; always restore in backwards order
    pop ecx     ; restore counter
    pop eax     ; restore number of arguments
    pop ebx     ; restore argument address

    inc ecx     ; increase our counter by 1
    add ebx, 4  ; move to next argument in the array

    ; the loop
    cmp ecx, eax        ; if ecx not equal to eax
    jne begin_for_loop  ; jmp to loop, else exit


    mov esp,ebp
    pop ebp
    ret

预期输出:

$ ./asm5 me you them us
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us

有问题的输出:

$ ./asm5 me you them us *
Arguments = ./asm5
Arguments = me
Arguments = you
Arguments = them
Arguments = us
Arguments = asm1
Arguments = asm1.asm
Arguments = asm1.o
Arguments = asm2
Arguments = asm2.asm
Arguments = asm3
Arguments = asm3.asm
Arguments = asm4
Arguments = asm4.asm
Arguments = asm5
Arguments = asm5.asm
Arguments = asm-template.asm
Arguments = compile-asm.sh
Arguments = cpp_libs

在 POSIX 系统上,如果您从 shell 启动程序,shell 将执行所谓的 globbing,扩展 * 并用匹配的文件替换它;结果将用作调用程序的参数。

你不能做任何事情来阻止它进入你的程序,你看到的参数确实是它从 shell 获得的参数(IOW,它们是已传递给 exec 的参数) .

如果您想在从 shell 启动程序时将文字 * 传递给您的程序,则必须引用它。

./asm5 me you them us "*"

当然 none 如果某些其他程序启动您的程序并将参数直接传递给 exec,而没有 shell 妨碍,当然会发生这种情况。


Replaced:

; the loop
         cmp ecx, eax        ; if ecx not equal to eax
         jne begin_for_loop  ; jmp to loop, else exit

With:

; the loop
         cmp ecx, eax        ; if ecx not equal to eax
         jmp begin_for_loop  ; jmp to loop, else exit

And I found a bigger issue where the program prints ENV variables to the screen.

这是因为您忽略了终止 argv 参数列表的 NULL,而您正在继续阅读接下来的内容;在您的情况下,这恰好是环境内存块。