如何将数组中特定点的值存储到寄存器中,反之亦然

时间:2012-04-12 03:20:17

标签: c assembly inline-assembly

编辑:这是使用AT& T语法

我正在使用GAS汇编程序学习汇编,并且必须编写一个程序,我在其中比较数组中的int值并根据比较更改值。我在C中使用内联汇编编写它。我知道对于一个基本变量,比如int i,我将值存储在寄存器eax中,其中包含以下行:

movl i, %eax

但是现在说我有变量a [2] [2]并且我想将[1] [1]移动到%eax中。明显的错误答案是:

movl a[1][1], %eax

我在表达式后得到错误垃圾'[1] [1]'。我如何将二维数组的值移动到寄存器中?谢谢!

2 个答案:

答案 0 :(得分:3)

由您将a [1] [1]转换为线性地址。换句话说,我们必须采用a[1][1]并计算从a开始的距离。我们首先计算一行的大小 - 在这种情况下,为2个整数。因此,(在int中工作,暂时)第0行的开头是偏移0,第1行偏移2,(如果有更多行)等等。然后我们在该行中添加偏移量。最后,我们根据单个项目的大小来扩展它。

从那里,我们有几种可能性。一个是我们只需要一个固定的位置 - 无论如何我们都会得到a[1][1]。另一个是我们真正关注的是a[i][j],其中ij恰好是1,但也可能是其他尺寸。

首先,我们可以使用汇编程序可以做一些数学计算我们的地址的事实。

// one row down times 2 ints per row + offset of 1 into last row, all times size of int
movl a + (1 * 2 + 1)*4, eax

在第二种情况下,我们假设i中的esij中的ebx。在这种情况下,我们必须自己做数学运算(抱歉,目前我将使用英特尔语法 - 我只是更习惯于它):

shl esi, 1    ; i * 2
add esi, ebx  ; i * 2 + j
shl esi, 2    ;(i * 2 + j) * 4

mov eax, a[esi]

x86实际上可以组合这些常用于寻址的操作,因此您不必像上面那样将它们作为单独的指令执行,因此我们可以很容易地将其减少到:

shl esi, 1
mov eax, a[esi][ebx]

最后可能需要一些解释 - 至少对MASM(可能还有气体,我猜)汇编器知道,因为你正在加载eax的值,你正在工作以4字节数量,因此它自动将偏移量缩放4。

答案 1 :(得分:2)

我对AT& T语法不是100%肯定所以我会发布我的英特尔解决方案以及我转换后的AT& T以防万一。

基本上,需要首先查找数组的值,然后才能进行交换。

英特尔语法

mov ecx, a  ;move the pointer to the 2D array into a register first
mov ecx, [ecx + 04h] ;walk to the a[1] dimension (4h happens to be the size of a pointer on my system)
mov eax, [ecx + 04h] ;eax now holds the value of a[1][1] and ecx still holds the memory location of a[1]
;do stuff with the eax register
mov DWORD PTR SS: [ecx + 4h], 1h ;change the value of a[1][1]

AT& T语法

   movl a, %ecx
   movl 4%(ecx),%ecx
   movl 4%(ecx),%eax
   ; do stuff with eax
   movl $1,4%(ecx)

编辑:如果您有一个固定大小的数组,Jerry的解决方案可能会更好,因此您可以计算线性地址,但这也适用于动态分配的2D数组。