编辑:这是使用AT& T语法
我正在使用GAS汇编程序学习汇编,并且必须编写一个程序,我在其中比较数组中的int值并根据比较更改值。我在C中使用内联汇编编写它。我知道对于一个基本变量,比如int i,我将值存储在寄存器eax中,其中包含以下行:
movl i, %eax
但是现在说我有变量a [2] [2]并且我想将[1] [1]移动到%eax中。明显的错误答案是:
movl a[1][1], %eax
我在表达式后得到错误垃圾'[1] [1]'。我如何将二维数组的值移动到寄存器中?谢谢!
答案 0 :(得分:3)
由您将a [1] [1]转换为线性地址。换句话说,我们必须采用a[1][1]
并计算从a
开始的距离。我们首先计算一行的大小 - 在这种情况下,为2个整数。因此,(在int中工作,暂时)第0行的开头是偏移0,第1行偏移2,(如果有更多行)等等。然后我们在该行中添加偏移量。最后,我们根据单个项目的大小来扩展它。
从那里,我们有几种可能性。一个是我们只需要一个固定的位置 - 无论如何我们都会得到a[1][1]
。另一个是我们真正关注的是a[i][j]
,其中i
和j
恰好是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
中的esi
和j
中的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]
movl a, %ecx
movl 4%(ecx),%ecx
movl 4%(ecx),%eax
; do stuff with eax
movl $1,4%(ecx)
编辑:如果您有一个固定大小的数组,Jerry的解决方案可能会更好,因此您可以计算线性地址,但这也适用于动态分配的2D数组。