c++ - 内联 asm 缓冲区循环

标签 c++ arrays assembly loops

好的,这是我的问题。我想循环使用一个简单的字符缓冲区 内联汇编和 VC++;

我的计划是创建一个循环,尽可能快地从内存中读取信息

这是我的代码

char buffer[howmany];
memset(buffer,33,howmany);
char arr = 0;
__asm
{
MOV     eax,seg buffer ;operand size conflict
MOV     eds,eax
MOV ecx,[howmany]
MOV     ebx,ip
MOV     arr, ES::buffer[ecx] ;operand size conflict
                             ;inline assembler syntax error in 'third operand'
                             ;found 'bad token'
LOOP    ebx ;inline assembler syntax error in 'opcode'; found 'bad token'
                ; 'LOOP' : identifier is reserved word
}

我对汇编很陌生,但这似乎是正确的,但它不起作用?我不确定为什么。提前致谢。

最终解决方案

__asm
{
    LEA         esi, buffer
    MOV      ecx,howmany
    buf_loop:   
    mov         eax, [esi]
    inc         esi
    dec         ecx
    jnz         buf_loop
}

最佳答案

首先,没有EDS,只有DS。即使在 32 位模式下,段寄存器仍然是 16 位。

其次,除非你正在使用像 DOS 扩展器这样的古老系统,或者一些非常不寻常的东西(与 Windows、Linux、OS/X、BSD 等典型的桌面/服务器操作系统有很大不同),否则你应该' 在任何情况下修改任何段寄存器。大多数当前系统使用“平面”内存模型,其中操作系统将所有1 段寄存器设置为基数为 0 和内存顶部的限制,因此您永远没有任何理由修改他们中的任何一个。

不幸的是,虽然说您的代码错误很容易,但要说什么是正确的却有点难——您还没有充分说明您想要做什么。现在,看起来您正在从缓冲区复制,但每次循环都会覆盖您在上一次迭代中写入的值,因此您最好只复制最后一个字并完成。为了通过缓冲区循环完成很多工作,您需要将其复制到相同(或更大)大小的目标缓冲区:

mov ecx, howmany
mov esi, offset FLAT:source
mov edi, offset FLAT:dest
rep movsd

正如其他人已经指出的,循环指令的操作数是标签,而不是寄存器。他们似乎没有指出的是,对于现代 CPU(比原来的 Pentium 更新的任何东西),您通常希望完全避免使用 LOOP 指令。然而,只是为了争论,执行上述移动的循环看起来像:

    mov ecx, howmany
    mov esi, offset FLAT:source
    mov edi, offset FLAT:dest
move_loop:
    lodsd
    stosd
    loop move_loop

对于现代 CPU,通常最好使用更多但更简单的指令。

; same setup as above
move_loop:
    mov eax, [esi]
    mov [edi], eax
    inc esi
    inc edi
    dec ecx
    jnz move_loop

事情的另一面是,在这种情况下,它不太可能重要——除非它都适合缓存,像这样的 block 移动几乎总是受到内存带宽的限制——移动不会得到快得多,但要获得最后一点改进,您需要使用 SSE 指令/寄存器。

编辑:最后一个细节。 VC++(以及其他语言)不允许您在 _asm block 内定义标签,因此如果您需要标签,您可以执行以下操作:

_asm {
    mov ecx, howmany
    mov esi, offset FLAT:source
    mov edi, offset FLAT:dest
}

move_loop:

_asm {
    lodsd
    stosd
    loop move_loop
}

1嗯,不是所有的 -- FS 和可能的 GS 不会这样,但 CS、DS、ES 和 SS 会这样。无论如何您都不想更改它们中的任何一个(事实上,尝试这样做通常只会让您的程序关闭)。

关于c++ - 内联 asm 缓冲区循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1932263/

相关文章:

c - 为什么我不能在 C 中使用一维数组的输入值?

c++ - Thunking __stdcall 函数与堆栈调整

arrays - 随机存取存储器如何工作?为什么是恒定时间随机访问?

string - 交换字符串的第一个和最后一个字符会导致段错误

C++ 枚举名称重叠

c++ - 当源不可用时,找到 Visual Studio 2015 调试器读取符号定义的位置

PHP数组到json可读输出

python - 如何以编程方式从十六进制中检索 unicode 字符?

c++ - 使用智能指针时递归函数中的段错误

c++ - valgrind 中的一些错误