2015-12-15 5 views
2

Я пишу код, который печатает второй аргумент программы. Я понимаю, что ebp+8 содержит количество аргументов, ebp+12 имеет адрес имени программы и т. Д. До сих пор у меня есть:Печать 2 аргумент командной строки

%include "asm_io.inc" 

SECTION .data 
err1: db "Incorrect number of command line arguments",10,0 

SECTION .text 
    global asm_main 

asm_main: 
    enter 0,0 
    pusha 

    mov eax, dword [ebp+8] 
    cmp eax, dword 2 
    jne ERR1 

    mov eax, dword [ebp+16] ; prints 1st letter of 2nd argument 
    mov al, byte[eax] 
    call print_string 
    jmp asm_main_end 


ERR1: 
    mov eax, err1 
    call print_string 
    jmp asm_main_end 

asm_main_end: 
    call print_nl 
    popa     ; restore all registers 
    leave      
    ret 

Исполняемый называется lynarr. Когда я выполняю lynarr abcd, я могу напечатать название программы (то есть lynarr), но я не понимаю, как напечатать второй аргумент. Я использую redhat-linux и nasm 2.10.07. Есть идеи?

ответ

4

dword [ebp+12] - указатель на массив указателей строк. Первый элемент этого массива является указателем на первую строку, второй - указателем на вторую строку и т. Д. Каждый указатель имеет ширину в 32 бита (4 байта).

Для получения указателя на вторую строку потребуется получить указатель на dword [ebp+12] + 4. Вы не можете сделать это непосредственно в адресации x86. Вы можете сделать это, переместив dword [ebp+12] в регистр, например EAX, добавьте 4 к нему (так как указатель имеет ширину 4 байта), а затем разыщите его, чтобы получить указатель на вторую строку.

Заменить:

mov eax, dword [ebp+16] ; prints 1st letter of 2nd argument 
mov al, byte[eax] 
call print_string 

С:

mov eax, dword [ebp+12] 
mov eax, [eax+4]   ; EAX = pointer to 2nd argument 
call print_string 

Это распечатать второй аргумент. Первый аргумент может быть распечатана с:

mov eax, dword [ebp+12] 
mov eax, [eax]   ; EAX = pointer to 1st argument 
call print_string 

Конечно mov eax, [eax+8] получит 3-й аргумент и так далее.

Вы не можете использовать print_string для печати одного символа в регистре (например, AL). EAX должен быть указатель на строку NUL (\ 0) завершенную строку.


Что-то еще вы можете сделать, это использовать scaled index addressing пошагово массив (например, ваши аргументы):

mov ebx, dword [ebp+12] 
xor esi, esi   ; Index of first argument (index=0) 
mov eax, [ebx+esi*4] ; EAX = pointer to 1st argument 
call print_string 
inc esi     ; Next argument (index=1) 
mov eax, [ebx+esi*4] ; EAX = pointer to 2nd argument 
call print_string 
inc esi     ; Next argument (index=2) 
mov eax, [ebx+esi*4] ; EAX = pointer to 3rd argument 
call print_string 

С этой идеей, вероятно, можно увидеть, как вы можете создать цикл, который идет через аргументы. Я оставляю это как упражнение для читателя. Это еще один удобный quick reference для режимов адресации.

+1

Спасибо! Я пытался сразу перейти на 'ebp + 16', что я теперь вижу неправильно. Кроме того, я не знал, что 'print_string' не может использоваться для печати AL. Большое спасибо за это! – Sally

+0

Да, я это видел. Сначала вам нужно было разыменовать [ebp + 12], а затем добавить 4. Вы были близки, зная, что 4 нужно добавить, чтобы перейти к следующему элементу. Для начала нужно было иметь правильный указатель. –

+1

@ Я добавил раздел, касающийся использования масштабированной адресной адресации, которую вы, возможно, сочтете полезной позже. –

Смежные вопросы