Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在字符串操作中使用DI寄存器_C_Assembly_X86 - Fatal编程技术网

C 在字符串操作中使用DI寄存器

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_

我正在看一个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_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用于传递参数,但我的问题是,为什么不使用特定寄存器,为什么不使用累加器或堆栈?这是由体系结构的定义,即体系结构。