通过汇编寻址逻辑反向推导C语言二维数组宏P、Q的取值
推导原理
C语言中int类型占4字节,二维数组按行优先存储,arr[M][N]的元素arr[x][y]的字节偏移计算公式为:(x * N + y) * 4
其中N是二维数组的列数,也就是每行的元素个数。我们可以结合这个公式,对应汇编中的地址计算逻辑,反向推导出P和Q的取值。
变量对应关系
首先明确汇编寄存器和C变量的对应:
%edi/%rdi对应函数入参i%esi/%rsi对应函数入参j
推导P的取值
mat2的定义为int mat2[Q][P],所以mat2[j][i]的字节偏移为 (j * P + i) * 4。
我们对应汇编中读取mat2的相关代码一步步计算:
leaq (%rsi,%rsi,2), %rax # rax = j + 2*j = 3j leaq (%rsi,%rax,4), %rdx # rdx = j + 3j*4 = 13j leaq (%rdx,%rdx), %rax # rax = 13j + 13j = 26j addq %rdi, %rax # rax = 26j + i movl mat2(,%rax,4), %ecx # 读取地址为 mat2 + rax*4 的值
可以看到汇编计算的mat2[j][i]偏移为(26j + i)*4,和C语言的偏移公式对比:(j * P + i)*4 = (26j + i)*4
两边约去公共项后可得 P = 26。
推导Q的取值
mat1的定义为int mat1[P][Q],所以mat1[i][j]的字节偏移为 (i * Q + j) * 4。
我们对应汇编中写入mat1的相关代码一步步计算:
leaq 0(,%rdi,8), %rdx # rdx = 8*i subq %rdi, %rdx # rdx = 8i - i =7i leaq 0(,%rdx,4), %rax # rax = 7i *4 = 28i addq %rax, %rsi # rsi = 28i + j movl %ecx, mat1(,%rsi,4) # 写入地址为 mat1 + rsi*4 的值
可以看到汇编计算的mat1[i][j]偏移为(28i + j)*4,和C语言的偏移公式对比:(i * Q + j)*4 = (28i + j)*4
两边约去公共项后可得 Q = 28。
最终结果
#define P 26 #define Q 28
注:你之前推导的表达式有误,错误原因是没有按汇编指令顺序分步计算寄存器值,按单条指令的运算逻辑逐行计算就能得到正确的偏移表达式。
内容的提问来源于stack exchange,提问作者Elie Meouchy
相关产品推荐
相关产品推荐

