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

标签 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_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

我了解基于指针和堆栈指针操作发生的部分以及其他操作,我想知道 put 有什么用

movl    $.LC0, %edi

如何将测试“Hello world”的地址从数据 block 加载到目标寄存器中解决这个问题,我们可以将该地址加载到累加器中并让 printf 处理它。我不习惯用汇编语言编程,但我可以弄清楚程序在做什么,我是否在这里遗漏了一些明显的东西? 谷歌搜索显示它们用于字符串操作,但没有人说为什么?

最佳答案

首先,您对 printf 的调用可能通过寄存器而不是堆栈传递参数,因为它是以这种方式优化的,或者因为它在编译期间的属性设置为 __fastcall (MSVC) 或 __attribute__((fastcall))

%esi%esi 寄存器用于字符串操作,因为它们对字符串指令具有意义,例如 cmps lodsmovsscasstosoutsins 。这些指令使用目标和源寄存器来快速顺序访问字节/字/双字字符串。它们可以在循环中使用,以进行已知在内存中连续执行的简单操作,并且通过消除指针操作和限制检查的需要,与循环前缀结合可以缩短执行时间。

一个很好的例子是 movs 指令(它还有另一种形式,如 movsbmovswmovsd)。如果您想编写一个没有字符串指令的简单字符串复制过程,您可以编写如下内容:

; 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],并递增 esiedi,然后递减 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

关于c - 在字符串操作中使用 DI 寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24742381/

相关文章:

C 库在 Postgres 中给出 '__gxx_personality_v0 ' 错误

c++ - 写入多个文件描述符

c - 保护 x86-64 上的内存

C 反汇编为 ARMv6 : Meaning of Dot (. ) 在标签之前

c - 什么是 __i686.get_pc_thunk.bx?为什么我们需要这个电话?

x86 - AVX2 矢量化 256 位查找表(32 个无符号字符)

c++ - 从 dll 函数调用中正确获取 Windows 版本?

assembly - 计算汇编语言指令的成本

x86 - 断点在宽松内存模型上的行为

c - 为什么没有打印出来?