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


好的,这是一个可以帮助你实现统计文件单词数量的C语言程序示例: ```c #include <stdio.h> #include <string.h> int main() { char file_name[100]; char buffer[1024]; int words = 0; FILE *fp; printf("请输入文件名:"); fgets(file_name, 100, stdin); // 删除文件名中的换行符 file_name[strcspn(file_name, "\n")] = 0; fp = fopen(file_name,"r"); if (fp == NULL) { printf("无法打开文件:'%s' \n", file_name); return 0; } while (fgets(buffer, 1024, fp)) { // 统计当前行的单词数量 int i = 0, len = strlen(buffer); while (i < len) { // 跳过开头的空格 while (i < len && buffer[i] == ' ') i++; // 如果达到字符串结尾,退出循环 if (i == len) break; // 统计一个单词 words++; // 移动到下一个空格 while (i < len && buffer[i] != ' ') i++; } } fclose(fp); printf("文件'%s'中的单词数量:%d \n", file_name, words); return 0; } ``` 你可以通过调用`fgets()`函数来获取用户输入的文件名,然后通过`fopen()`函数打开这个文件读取其中的内容。在读取文件时,每次使用`fgets()`函数可以从文件中获取一行文本。然后你可以遍历该行字符,统计其中的单词数量,并累计到总单词数量中。最后输出即可。 请注意:在编写实际的命令行程序时,需要实现很多错误处理和边界处理逻辑,并进行大量的测试以确保程序的正确性。以上示例只是为了说明如何通过`fgets()`来实现文件输入输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值