问题描述
我是 X86 汇编语言的初学者.我知道如何使用内置函数从 stdin 读取和写入 stdout,但我不确定如何使用普通的汇编代码(即操作寄存器和利用系统调用)来做到这一点.
I'm a beginner in X86 assembly language. I know how to read from stdin and write to stdout using build-in functions, but I'm not sure how to do it with plain assembly code(i.e. manipulating registers and taking advantage of system calls).
#include <stdio.h>
#include <unistd.h>
int main(){ /* copy input to output */
char buf[BUFSIZ];
int n;
while ((n = read(0, buf, BUFSIZ)) > 0)
write(1, buf, n);
return 0;
}
这是我写的 C 代码,首先从标准输入(由数字 0 表示)读取然后写入标准输出(由数字 1 表示).有人能帮我把它转换成普通的汇编代码吗(请不要调用读取"和调用写入")?
This is the C code I wrote to first read from the standard input (represented by number 0) then write to the standard output (represented by number 1). Can anybody help me to convert it into plain assembly code(NO "call read" & "call write" please)?
语法无关紧要,但首选 32 位 AT&T,因为我一直在使用它:) 提前致谢!
The syntax doesn't matter, but 32-bit AT&T is preferred since I have been using it:) Thanks in advance!
推荐答案
对于您使用的任何操作系统,系统调用都应该有详细记录.例如,请参见 此处.
The system calls should be well-documented for whatever operating system you're using. For example, see the Linux ones here.
因此,在您的情况下,要从标准输入读取,您将加载 eax
与 3,ebx
与描述符 0
,ecx
为缓冲区地址,edx
为长度.
So, in your case, to read from standard input, you would load eax
with 3, ebx
with the descriptor 0
, ecx
with the buffer address and edx
with the length.
然后使用 int 0x80
(32 位 Linux)或 syscall
(64 位模式)调用系统调用接口,具体取决于您的平台.或者您可以使用 sysenter
进行优化的 32 位系统调用,但它需要其他设置,不建议直接使用.请参阅权威指南Linux 系统调用了解更多详情.
Then call the syscall interface with int 0x80
(32-bit Linux) or syscall
(64-bit mode), depending on your platform. Or you can use sysenter
for optimized 32-bit system calls, but it requires other setup and using it directly is not recommended. See The Definitive Guide to Linux System Calls for more detail.
eax
寄存器将(在从 read
系统调用返回时)包含成功读取的字节数,否则将包含错误指示.
The eax
register will then (on return from the read
syscall) contain the number of bytes read on success, or an error indication otherwise.
我手边没有 Linux 机器,但它应该是这样的:
I don't have a Linux box handy but it would be something like:
section .bss
buf resb 1 ; 1-byte buffer
section .text
global _start
_start:
loop1: mov edx, 1 ; max length
mov ecx, buf ; buffer
mov ebx, 0 ; stdin
mov eax, 3 ; sys_read
int 80h
cmp eax, 0 ; end loop if read <= 0
jle lpend1
mov edx, eax ; length
mov ecx, buf ; buffer
mov ebx, 1 ; stdout
mov eax, 4 ; sys_write
int 80h
jmp loop1 ; go back for more
lpend1:
mov eax, 1
mov ebx, 0
int 80h ; _exit(0)
这就是循环的基本结构.如前所述,这是从内存中编写的,因此可能需要进行一些调试,我什至可能有一些助记符错误.但这应该是一个开始.
That would be the basic structure of your loop. As stated, this was written from memory so it may need some debugging, I may even have some of the mnemonics wrong. But that should hopefully be a start.
这篇关于X86 从 stdin 读取并写入 stdout 而不引用标准库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!