C 在字符串操作中使用DI寄存器
我正在看一个C程序的编译器输出,只是为了学术目的,碰巧得到了以下输出C 在字符串操作中使用DI寄存器,c,assembly,x86,C,Assembly,X86,我正在看一个C程序的编译器输出,只是为了学术目的,碰巧得到了以下输出 .file "test.c" .section .rodata .LC0: .string "Hello World" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_
.file "test.c"
.section .rodata
.LC0:
.string "Hello World"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
我了解基于指针和堆栈指针操作的发生部分以及其他操作,我想知道放置的用途是什么
movl $.LC0, %edi
movl $.LC0, %edi
如何将测试“Hello world”的地址从数据块加载到目标寄存器解决了这个问题,我们可以将该地址加载到累加器中,让printf处理它。我不习惯在汇编中编程,但我能看出程序在做什么,我是否遗漏了一些明显的东西?
Google搜索显示它们被用于字符串操作,但没有人说为什么?首先,您对
printf
的调用可能是通过寄存器而不是堆栈传递参数,因为它以这种方式进行了优化,或者因为编译期间它的属性被设置为\uu fastcall
(MSVC)或\uu attribute__((快速调用))
%esi
和%esi
寄存器用于字符串操作,因为它们对字符串指令有意义,例如cmps
、lods
、movs
、scas
、stos
、out
或ins
。这些指令使用目标和源寄存器进行快速排序对字节/字/双字字符串的tial访问。它们可以在循环中使用,以进行已知可在内存中连续执行的简单操作,并且通过消除指针操作和限制检查的需要,结合循环前缀可以缩短执行时间
这方面的一个很好的例子是movs
指令(它还有另一种形式,如movsb
,movsw
,movsd
)。如果您想编写一个没有字符串指令的简单字符串复制过程,可以编写如下内容:
; IN: EAX=source&, EBX=dest&, ECX=count
; OUT: nothing
copy:
.loop:
cmp ecx, 0
jz .end
dec ecx
mov al, byte [eax+ecx]
mov byte [ebx+ecx], al
jmp .loop
.end:
ret
movsb
指令将[esi]
复制到[edi]
,递增esi
和edi
,然后递减ecx
。记住这一点,您可以编写类似的代码:
; IN: ESI=source&, EDI=dest&, ECX=count
; OUT: nothing
copy:
.loop:
jecxz .end
movsb
jmp .loop
.end:
ret
使用循环前缀,可以再次加快整个操作
; IN: ESI=source&, EDI=dest&, ECX=count
; OUT: nothing
copy:
rep movsb
ret
我将对用户35443回答是和否 我想知道推杆有什么用
movl $.LC0, %edi
movl $.LC0, %edi
由于您使用的是64位Linux(通过使用rbp
),因此在64位区域中,参数在寄存器中传递。rdi
包含第一个参数,rsi
第二个参数,rdx
第三个参数,rcx
第四个参数,r8
第五个参数,r9
第六个参数;任何其他参数都在堆栈上传递
我们可以把这个地址加载到累加器中,然后
printf处理它
不!在使用汇编时,您需要阅读和理解您正在使用的操作系统的ABI,并将其跟踪到T!如果您使用的是Windows,则第一个参数将位于rcx
中。它与源和目标无关
“累加器”实际上是
printf
和所有vararg函数的一个参数。r/eax
包含在xmm
寄存器中传递的浮点数,因为在您的示例代码中不传递浮点数,eax
设置为0。编译器可以通过寄存器而不是e stack.movl$.LC0,%edi是printf函数的参数。我知道edi用于传递参数,但我的问题是,为什么不使用特定寄存器,为什么不使用累加器或堆栈?这是由体系结构的定义,即体系结构。