Печать аргументов командной строки x86 Assembly - PullRequest
0 голосов
/ 21 января 2019

Во-первых, я новичок в сборке, но имею неплохой опыт работы с c ++.Моя проблема проистекает из учебника, за которым я следовал Аргументы командной строки, используя сборку .

Когда программа запускается, она делает все, что должна делать, в соответствии с учебником, который отображает списоквходных данных программы: ./asm1 arg1 arg2 arg3

Проблема заключается в том, что в качестве аргумента вы указываете астриск: ./asm1 *

Эффективно работает / usr / bin / ls на CWD.

Мой вопрос: как мне предотвратить это, и любые советы о том, как лучше реализовать эту программу.

Заменено:

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

На:

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

И я обнаружил большую проблему, когдаПрограмма выводит переменные ENV на экран.

Ниже приведена оригинальная программа:

; 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

1 Ответ

0 голосов
/ 21 января 2019

В системах POSIX, если вы запускаете программу из оболочки , оболочка выполнит так называемое глобализация, расширив * и заменив его соответствующими файлами; результат будет использован в качестве аргументов для вызова вашей программы.

Вы не можете ничего сделать, чтобы предотвратить это от вашей программы, аргументы, которые вы видите, действительно те, что были получены из оболочки (IOW, это аргументы, которые были переданы exec).

Если вы хотите передать литералу * вашей программе при запуске из оболочки, вам придется заключить ее в кавычки.

./asm5 me you them us "*"

Конечно, ничего этого не произойдет, если какая-то другая программа запустит вашу программу, передавая аргументы прямо в exec, не мешая оболочке.


Заменены:

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

С:

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

И я обнаружил еще большую проблему, когда программа выводит переменные ENV на экран.

Это происходит из-за того, что вы игнорируете NULL, который завершает список аргументов argv, и вы продолжаете читать, что дальше; в вашем случае это блок памяти среды.

...