2016-12-22 35 views
1

我想打电话从32位汇编写系统调用,代码即时通讯现在使用:混合整数和字符串在strace的输出

.section .rodata    # read-only data 
msg: 
    .ascii "hello"    # not null-terminated string called "msg" 
len: 
    .long 5     # length of "msg" 


.section .text    # actual runnable code 
.globl  _start 
.type  _start, @function 
_start: 
    movl $4, %eax   # syscall number into eax (4 is write) 
    movl $1, %ebx   # argument number 1 into ebx (stdout) 
    movl $msg, %ecx   # argument number 2 into ecx 
    movl len, %edx   # argument number 3 into edx 
    int  $0x80 

    movl $1, %eax   # syscall number into eax (1 is exit) 
    movl $0, %ebx   # argument number 1 into ebx (exit code) 
    int  $0x80 

它编译并运行正常,打印字符串“你好”到控制台,但是当我使用strace的‘看’写发生时,我得到以下的输出:

execve("./main", ["./main"], [/* 86 vars */]) = 0 
strace: [ Process PID=22529 runs in 32 bit mode. ] 
write(1, "hello", 5hello)     = 5 
exit(0)         = ? 
+++ exited with 0 +++ 

我想知道是什么原因导致第三arugment被5hello而不是5

+2

没有什么,'你好'在那里是你的程序的实际输出。重定向strace或你的代码的输出,所以他们不会穿插。 – Jester

回答

2

没什么, hello在那里是你的程序的实际输出。这里是正在发生的事情:

  1. strace的拦截系统调用写
  2. strace的打印调用名称和参数:write(1, "hello", 5。请注意这转到stderr。由于某种原因,它不打印关闭)呢。
  3. write系统调用得到执行,因此hello被打印到stdout
  4. strace再次需要获得控制权,以便它可以打印返回值,它将与闭合圆括号一起给出) = 5

在你的情况下,stdoutstderr指的是同一个终端。重定向strace或你的代码的输出,所以他们不会穿插。

+0

我真的不相信我错过了,谢谢。我会在3分钟内接受你的回答 – Maciej

+0

我相信'strace'钩子会在调用系统调用之前先输出参数(逻辑上,因为调用可以自由修改),然后返回时它会用返回值。与此同时,写作是与“你好”的工作。 – Ped7g

+0

@ Ped7g:这并不能完全解释为什么'strace'不会等待打印')= retval'。原因是系统调用可能会阻塞,所以它会在调用之前打印调用的东西,并在调用之后打印返回的东西。通过运行'strace sleep 1'可以很容易地看到这一点。当系统调用被信号中断(例如,如果你在'nanosleep'或'pkill -WINCH sleep'期间发送一个不会做任何事情的信号'),strace甚至会打印额外的东西。 –

相关问题