为什么这段32位汇编代码无法正确实现文件读取与写入?
问题分析与解决
核心问题原因
- fprintf参数传递错误:
最初使用push dword number时,传递的是number变量的内存地址而非读取到的字节内容,%d格式符会打印该地址值,也就是你看到的“类似偏移量的数值”;改成push dword [number]后,因number仅占1字节,push操作会将该字节与后续3个字节的垃圾数据一起作为32位整数传递,导致打印随机值。 - 格式符使用不当:
若要原样复制文件的ASCII内容,应使用%c格式符打印字符;若需打印字节的数值,则需将1字节数据扩展为完整的32位整数后再传递。 - fread参数顺序不规范(虽未影响当前结果):
msvcrt的fread原型为size_t fread(void *ptr, size_t size, size_t count, FILE *stream),C调用约定要求参数从右到左入栈,正确顺序应为stream → count → size → ptr,你当前代码颠倒了size和count的顺序,虽因两者均为1未引发问题,但需修正以符合规范。
修正后的代码
bits 32 global start extern exit, fread, fprintf, fopen, fclose import exit msvcrt.dll import fopen msvcrt.dll import fclose msvcrt.dll import fread msvcrt.dll import fprintf msvcrt.dll segment data use32 class=data reading_file db "trial.txt", 0 access_mode1 db "r", 0 printing_file db "trial2.txt", 0 access_mode2 db "w", 0 read_descriptor resd 1 print_descriptor resd 1 number resb 1 print_format db "%c", 0 ; 用%c打印字符实现原样复制,若需打印数值可改为%d并配合后续扩展逻辑 segment code use32 class=code start: ; 打开读取文件 push dword access_mode1 push dword reading_file call [fopen] add esp, 4*2 cmp eax, 0 je end_of_code mov [read_descriptor], eax ; 打开写入文件 push dword access_mode2 push dword printing_file call [fopen] add esp, 4*2 cmp eax, 0 je end_of_code mov [print_descriptor], eax read_loop: ; 修正fread参数顺序:stream → count → size → ptr push dword [read_descriptor] push dword 1 ; count push dword 1 ; size push dword number call [fread] add esp, 4*4 cmp eax, 0 je end_of_code ; 传递字节内容,%c仅取低字节,push dword不会影响结果 push dword [number] push dword print_format push dword [print_descriptor] call [fprintf] add esp, 4*3 jmp read_loop end_of_code: ; 关闭文件 push dword [read_descriptor] call [fclose] add esp, 4 push dword [print_descriptor] call [fclose] add esp, 4 push dword 0 call [exit]
关于同时操作两个文件
完全可以同时操作多个文件,只要每个文件拥有独立的文件描述符即可,你代码中read_descriptor和print_descriptor的逻辑是正确的。
内容的提问来源于stack exchange,提问作者Diana R
相关产品推荐
相关产品推荐

