32位汇编语言学习笔记(44)--显示命令行参数(3)

时间:2022-09-06 03:32:30


与前面的版本不同,这个是使用libc库版本的显示命令行参数程序,因为main函数并不是程序的入口点,而是由libc库的代码调用,所以命令行参数在栈上的位置有不同,先看示例程序:

[SECTION .data]			; Section containing initialised data

ArgMsg db "Argument %d: %s",10,0

[SECTION .bss] ; Section containing uninitialized data


[SECTION .text] ; Section containing code

global main ; Required so linker can find entry point
extern printf ; Notify linker that we're calling printf

main:
push ebp ; Set up stack frame for debugger
mov ebp,esp
push ebx ; Program must preserve ebp, ebx, esi, & edi
push esi
push edi
;;; Everything before this is boilerplate; use it for all ordinary apps!

mov edi,[ebp+8] ; Load argument count into EDI
mov ebx,[ebp+12] ; Load pointer to argument table into EBX
xor esi,esi ; Clear ESI to 0
.showit:
push dword [ebx+esi*4] ; Push addr. of an argument on the stack
push esi ; Push argument number
push ArgMsg ; Push address of display string
call printf ; Display the argument # and argument
add esp,12 ; Stack cleanup: 3 parms x 4 bytes = 12
inc esi ; Bump argument # to next argument
dec edi ; Decrement argument counter by 1
jnz .showit ; If argument count is 0, we're done

;;; Everything after this is boilerplate; use it for all ordinary apps!
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp,ebp ; Destroy stack frame before returning
pop ebp
ret ; Return control to Linux

程序分析:
main:
    push ebp //保存旧的ebp
 mov ebp,esp //ebp = esp,保存栈指针到ebp
 push ebx //保存ebx
 push esi //保存esi
 push edi //保存edi

 mov edi,[ebp+8]  //ebp+4保存的是调用main函数后的返回地址,ebp+8,是main函数左边的第一个参数:argc,即命令行参数个数
 mov ebx,[ebp+12] //ebp+12保存的是argv,就是命令行参数字符串指针数组。
 xor esi,esi  //esi=0
.showit:
 push dword [ebx+esi*4] //把字符串参数压入堆栈
 push esi //压入参数编号(索引值)
 push ArgMsg //格式化字符串
 call printf //调用printf,显示这个字符串参数信息
 add esp,12  //清理栈
 inc esi  //esi=esi+1,下一个参数
 dec edi  //edi=edi-1,用于控制循环次数
 jnz .showit //如果edi不等于0,则继续循环,否则结束。循环次数是命令行参数个数。
 
 pop edi  //恢复edi寄存器
 pop esi      //恢复esi寄存器
 pop ebx     //恢复ebx寄存器 
 mov esp,ebp //esp=ebp,恢复函数调用开始时栈指针位置
 pop ebp //恢复ebp
 ret 

测试:

[root@bogon showargs3]# make
nasm -f elf -g -F stabs showargs3.asm
gcc showargs3.o -o showargs3
[root@bogon showargs3]# ./showargs3 p1 p2 p3 p4 p5
Argument 0: ./showargs3
Argument 1: p1
Argument 2: p2
Argument 3: p3
Argument 4: p4
Argument 5: p5