将linux中运行汇编代码的结果重定向到文本文件
我正在尝试编写一个 Python 脚本来测试我在汇编中编写的一些各种代码的输出与预期输出。但是我很难将输出重定向到文件中。 我编写了以下内容:
extern printf
LINUX equ 80H ; interupt number for entering Linux kernel
EXIT equ 1 ; Linux system call 1 i.e. exit ()
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
push rax
push rsi
push rdi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
pop rax
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 1 i.e. exit ()
mov rbx, 0 ; Error code 0 i.e. no errors
mov rcx, 5
int LINUX ; Interrupt Linux kernel
然后,我继续在控制台中执行以下操作:
nasm -f elf64 basic.asm
gcc -m64 -o basic basic.o
./basic
将 10 输出到屏幕。 但是,如果我输入
./basic > basic.txt
cat basic.txt
basic.txt 将显示为空文件。 我的总体目标是编写一个 shell 脚本,该脚本循环遍历每个程序集文件以编译并运行该文件,然后将该脚本的输出重定向到一个文件中。但是,除非我可以让它与单个文件一起工作,否则我无法执行此操作。 我想知道这与我对 printf 的调用有关吗?尽管我有一种幻觉,认为 printf 会写入 STDOUT。
提前致谢!
I'm trying to write a Python script to test the output of some various code I've written in assembly against an expected output. However I am having difficulty redirecting the output into a file.
I have written the following:
extern printf
LINUX equ 80H ; interupt number for entering Linux kernel
EXIT equ 1 ; Linux system call 1 i.e. exit ()
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
push rax
push rsi
push rdi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
pop rax
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 1 i.e. exit ()
mov rbx, 0 ; Error code 0 i.e. no errors
mov rcx, 5
int LINUX ; Interrupt Linux kernel
I then procede to do the following in the console:
nasm -f elf64 basic.asm
gcc -m64 -o basic basic.o
./basic
Which outputs 10 to the screen.
However if I enter
./basic > basic.txt
cat basic.txt
basic.txt appears as an empty file.
My overall goal is to write a shell script that loops over each assembly file to compiling and run the file and then redirect the output of this script into a file. However I cannot do this until I can get it to work with a single file.
I was wondering it it was something to do with my call to printf? Although I was under the illusion that printf writes to STDOUT.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的重定向是正确的;问题一定出在您正在生成的程序集中。
调试此类问题的工具是
strace
。在strace
下运行程序,显示:您可以清楚地看到所需的输出,但也有一些“杂散”写入。那个写是从哪里来的?
GDB 来救援:
很好,这是预期的调用写入。
这只是系统调用的返回。写入成功了吗? (我们知道它确实如此,因为我们在上面看到了它的输出,但让我们确认一下。)
很好。 Write 写入了预期的 3 个字符。
这是我们没想到的写法。从哪里来?
因此,您的系统调用执行了
write(2)
,而不是预期的exit(2)
。为什么会发生这种情况?因为您错误地定义了
EXIT
:从上面可以看出,
EXIT
在 32 位模式下应为 1,但在 64 位模式下应为 60。NR_write 怎么样? 64位模式下是1吗?
确实如此。这样我们就解决了“杂散写从何而来?”的问题。谜。将
EXIT
修复为 60,并在strace
下重新运行,我们现在看到:这仍然是不对的。我们应该调用
_exit(0)
,而不是_exit(1)
。看看x86_64
ABI,显示您的寄存器使用不正确:系统调用号应该在%rax
中,但参数在%rdi
、%rsi
、%rdx
等。修复该问题(并删除伪造的
mov rcx, 5
) ,我们终于从strace
获得了所需的输出:所以现在我们准备看看上述修复是否也解决了重定向问题。
在 strace 下重新运行,输出重定向:
显然我们对
write
的调用丢失了。它去哪儿了?好吧,stdout 输出默认是行缓冲的,并且在重定向到文件时会得到完全缓冲。也许我们缺少一个
fflush
调用?事实上,在退出之前添加对 fflush(NULL) 的调用可以解决问题:
我希望您今天学到了一些东西(我做到了;-)
Your redirection is correct; the problem must be in the assembly you are generating.
The tool to debug such problems is
strace
. Running your program understrace
, shows:You can clearly see your desired output, but also some "stray" write. Where is that write coming from?
GDB to the rescue:
Good, this is the expected call to write.
This is just the return from syscall. Did write succeed? (We know it did, since we see its output above, but let's confirm.)
Good. Write wrote the expected 3 characters.
This is the write we didn't expect. Where from?
So your syscall executed
write(2)
instead of expectedexit(2)
. Why did this happen?Because you've defined
EXIT
incorrectly:From above, you can tell that
EXIT
should be 1 in 32-bit mode, but 60 in 64-bit mode.What about NR_write? Is it 1 in 64-bit mode?
Indeed it is. So we have solved the "where did stray write come from?" puzzle. Fixing
EXIT
to be 60, and rerunning understrace
, we now see:That still isn't right. We should be calling
_exit(0)
, not_exit(1)
. A look at thex86_64
ABI, reveals that your register use is incorrect: syscall number should be in%rax
, but the arguments in%rdi
,%rsi
,%rdx
, etc.Fixing that (and deleting bogus
mov rcx, 5
), we finally get desired output fromstrace
:So now we are ready to see if above fixes also fixed the redirection problem.
Re-running under strace, with output redirected:
Clearly our call to
write
is missing. Where did it go?Well,
stdout
output is line buffered by default, and gets fully buffered when redirected to a file. Perhaps we are missing anfflush
call?Indeed, adding a call to
fflush(NULL)
just before exiting solves the problem:I hope you've learned something today (I did ;-)
尝试从 main 退出
Try exiting from main by