【问题标题】:Array value fetching in asm x64在 asm x64 中获取数组值
【发布时间】:2013-03-24 16:12:40
【问题描述】:

我有一个问题,asm 代码在与 C 混合时可以工作,但在带有适当参数的 asm 代码中使用时却不能。

;; array - RDI, x- RSI, y- RDX
getValue:   
   mov r13, rsi
   sal r13, $3
   mov r14, rdx
   sal r14, $2
   mov r15, [rdi+r13]
   mov rax, [r15+r14]

   ret

从技术上讲,我希望保持 rdi、rsi 和 rdx 寄存器不变,因此我使用其他寄存器。

我使用的是 x64 机器,因此我的指针有 8 个字节。从技术上讲,这段代码应该这样做:

int getValue(int** array, int x, int y) {
    return array[x][y];
}

它以某种方式在我的 C 代码中工作,但在 asm 中以这种方式使用时不起作用:

mov rdi, [rdi]    ;; get first pointer - first row
mov r9,  $4       ;; we want second element from the row
mov rax, [rdi+r9] ;; get the element (4 bytes vs 8 bytes???)
mov rdi, FMT      ;; prepare printf format "%d", 10, 0
mov rsi, rax      ;; we want to print the element we just fetched
mov eax, $0       ;; say we have no non-integer argument
call printf       ;; always gives 0, no matter what's in the matrix

有人可以看看这个并帮助我吗?提前致谢。

【问题讨论】:

    标签: arrays assembly 64-bit x86-64


    【解决方案1】:

    sal r14, $2 意味着元素是双字,因此ret 之前的最后一行不应加载 qword。此外,x86 有很好的缩放寻址模式,所以你可以这样做:

    mov rax, [rdi + rsi * 8]  ; load pointer to column
    mov eax, [rax + rdx * 4]  ; note this loads a dword
    ret
    

    这意味着您有一个指向的指针数组,这是不寻常的。你可以这样做,但这是故意的吗?

    【讨论】:

    • 好的,但是我现在怎么打印呢?问,因为我刚从 ASM 和 x64 开始,我不知道将 32 位值转换为 64 位值的方法(printf 将标准 8 字节寄存器作为第一个参数,所以“mov rsi,eax”不会工作)。
    • 您可以使用 movsxd rsi, eax 将其符号扩展为 64 位。如果它是未签名的或已知是肯定的,你可以mov esi, eax它。
    • 谢谢。这真的很棒。我之前测试过它,但是在将计算值分配给 rsi 之前将 eax 更改为 0 是我的愚蠢...再次感谢!
    【解决方案2】:

    这是一个标准的整数矩阵。

    int** array;
    sizeof(int*) == 8
    sizeof(int) == 4
    

    我的看法是,当我一开始拥有那个数组时,我有一个指向没有“空白”的内存空间的指针,它一个一个地保存所有指针(逐个索引),所以我说“让我们转到数组的第 rsi 个元素”,这就是我移动 rsi-th * 8 个字节的原因。所以现在我得到了同样的情况,但是指针应该指向一个整数空间,所以是 4 字节的项目。这就是我在那里移动 4 个字节的原因。

    我的想法错了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 2016-09-09
      • 2021-10-08
      • 1970-01-01
      相关资源
      最近更新 更多