32位汇编语言学习笔记(41)--fgets等函数的使用



在《32位汇编语言学习笔记(13)--函数的调用》曾分析过c函数的调用过程,对于c函数的默认调用约定cdecl,要求函数参数的压栈顺序是从右向左,由调用方来清理栈。下面示例程序会使用libc库的几个函数:
char *fgets( char *string, int n, FILE *stream );
int printf( const char *format [, argument]... );
int scanf( const char *format [,argument]... );

示例程序如下:

[SECTION .data]			; Section containing initialised data
	
SPrompt  db 'Enter string data, followed by Enter: ',0		
IPrompt  db 'Enter an integer value, followed by Enter:	 ',0
IFormat  db '%d',0
SShow    db 'The string you entered was: %s',10,0
IShow    db 'The integer value you entered was: %5d',10,0
	
[SECTION .bss]		; Section containing uninitialized data

IntVal   resd	1	; Reserve an uninitialized double word
InString resb 128	; Reserve 128 bytes for string entry buffer
		
[SECTION .text]		; Section containing code

extern stdin		; Standard file variable for input
extern fgets
extern printf	
extern scanf		
global main		; Required so linker can find entry point
	
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!

; First, an example of safely limited string input using fgets:
	push SPrompt	; Push address of the prompt string
	call printf	; Display it
	add esp,4	; Stack cleanup for 1 parm
	
	push dword [stdin]  ; Push file handle for standard input
	push 72		; Accept no more than 72 chars from keybd
	push InString	; Push address of buffer for entered chars
	call fgets	; Call fgets
	add esp,12	; Stack cleanup: 3 parms X 4 bytes = 12

	push InString	; Push address of entered string data buffer
	push SShow	; Push address of the string display prompt
	call printf	; Display it
	add esp,8	; Stack cleanup: 2 parms X 4 bytes = 8

; Next, use scanf() to enter numeric data:
	push IPrompt	; Push address of the integer input prompt
	call printf	; Display it
	add esp,4	; Stack cleanup for 1 parm

	push IntVal	; Push the address of the integer buffer
	push IFormat	; Push the address of the integer format string
	call scanf	; Call scanf to enter numeric data
	add esp,8	; Stack cleanup: 2 parms X 4 bytes = 8

	push dword [IntVal]	; Push integer value to display
	push IShow	; Push base string
	call printf	; Call printf to convert & display the integer
	add esp,8	; Stack cleanup: 2 parms X 4 bytes = 8
	
;;; 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

程序分析:
    这里只分析fgets函数的调用,其他类似。
push dword [stdin]  //stdin是libc库中的符号,表示标准输入,实际是一个地址,fgets调用需要的是一个句柄,而不是地址值,因此要通过间接寻址获取句柄值。(对应的入参是stream)
 push 72  //从标准输入读取的最大字符串长度是72。
 push InString //缓存地址,InString分配的空间是128个字节,所以最大长度设为72是没有问题的。
 call fgets //调用fgets
 add esp,12 //清理堆栈,压入了3个参数,使用了12个字节。

makefile文件内容:

charsin: charsin.o
	gcc charsin.o -o charsin
charsin.o: charsin.asm
	nasm -f elf -g -F stabs charsin.asm

测试:

[root@bogon charsin]# make
nasm -f elf -g -F stabs charsin.asm
gcc charsin.o -o charsin
[root@bogon charsin]# ./charsin
Enter string data, followed by Enter: hello world
The string you entered was: hello world

Enter an integer value, followed by Enter:       123456
The integer value you entered was: 123456


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值