汇编矩阵操作代码正确性审核及内存值异常问题排查
汇编代码审核:矩阵转置、列标量积及行元素统计
我从未接触过汇编语言,编写了一段代码要完成以下三个任务:
- 计算矩阵
arr1的转置并保存到arr2 - 计算
arr1第7列与第6列的标量积 - 统计
arr1第4行中满足a[i] <= -22 || a[i] > 81的元素数量及总和
但在内存中查看arr1和arr2时,数值不符合预期,请求审核代码正确性。代码如下:
.586P .MODEL FLAT, STDCALL _DATA SEGMENT arr1 DD -79, 59, 59, 93, -79, 84 DD -51, 43, -50, -94, 23, 70 DD -44, 97, -66, -17, 100, 82 DD -83, 76, 1, 55, -20, -34 DD -11, -51, -50, 55, -80, -28 DD 58, -60, 30, 60, 90, -46 DD 20, 82, -4, -93, -75, 35 arr2 DD 0, 0, 0, 0, 0, 0, 0 DD 0, 0, 0, 0, 0, 0, 0 DD 0, 0, 0, 0, 0, 0, 0 DD 0, 0, 0, 0, 0, 0, 0 DD 0, 0, 0, 0, 0, 0, 0 DD 0, 0, 0, 0, 0, 0, 0 rowCnt DD 7 colCnt DD 6 iter DD 0 arr1Offset DD 32 arr2Offset DD 24 arr2OffsetCnt DD 0 scalarProd SDWORD 0 var1 SDWORD 0 var2 SDWORD 0 varb DD -22 varc DD 81 condCnt DD 0 condSum SDWORD 0 compRes SDWORD 0 check SDWORD 0 _DATA ENDS _TEXT SEGMENT START: ; Transpose matrix mov ECX, rowCnt lea EBX, arr1 LOOP1: mov iter, ECX mov ECX, colCnt lea ESI, arr2 add ESI, arr2OffsetCnt LOOP2: mov EAX, [EBX] add [ESI], EAX add EBX, 4 add ESI, arr2Offset loop LOOP2 mov ECX, iter add arr2OffsetCnt, 4 loop LOOP1 ; scalar product of 7th and 6th columns lea EBX, arr1 add EBX, 24 lea ESI, arr1 add ESI, 20 mov ECX, rowCnt LOOP3: mov EAX, [EBX] mov var1, EAX mov EAX, [ESI] mov var2, EAX mov EAX, var1 imul EAX, var2 add scalarProd, EAX add EBX, 24 add ESI, 24 loop LOOP3 ;amount and sum of the elements of 4th row, that meets expectation (a[i] <= b(-22) || a[i]>c(81)) lea EBX, arr1 add EBX, 72 mov ECX, 6 LOOP4: mov compRes, 0 mov EAX, [EBX] mov check, EAX CMP EAX, varb jg C1 mov compRes, 1 C1: CMP EAX, varc jl C2 mov compRes, 1 C2: mov EAX, compRes CMP EAX, 1 jne C3 inc condCnt mov EAX, condSum add EAX, [EBX] mov condSum, EAX C3: add EBX, 4 loop LOOP4 RET _TEXT ENDS END START
一、矩阵转置部分错误
- arr2行偏移量错误:
arr2是转置后的矩阵,原arr1为7行6列,转置后应为6行7列,每行7个双字(DD),每个DD占4字节,因此每行的字节偏移应为7*4=28,但代码中arr2Offset设为24,导致元素写入位置错误,需改为28。 - 元素赋值方式错误:代码用
add [ESI], EAX累加值,虽arr2初始为0时首次累加等价于赋值,但逻辑错误,应改为直接赋值mov [ESI], EAX,避免后续潜在的累加问题。 - 冗余变量处理:
arr1Offset未被使用,可删除;用栈保存循环计数器替代内存变量iter,效率更高。
修正后的转置代码片段:
; 修正后的矩阵转置 _DATA SEGMENT ; ... 其他变量不变,仅修改arr2Offset arr2Offset DD 28 ; 7*4=28,对应arr2每行的字节数 ; ... _DATA ENDS _TEXT SEGMENT START: mov ECX, rowCnt lea EBX, arr1 LOOP1: push ECX ; 用栈保存循环计数器,替代iter变量 mov ECX, colCnt lea ESI, arr2 add ESI, arr2OffsetCnt LOOP2: mov EAX, [EBX] mov [ESI], EAX ; 直接赋值而非累加 add EBX, 4 add ESI, arr2Offset loop LOOP2 pop ECX add arr2OffsetCnt, 4 loop LOOP1
二、列标量积部分问题
- 列索引混淆:
arr1每行仅6列,不存在第7列。推测是你将列起始计数搞错(从1开始而非0),当前代码计算的是第6列(偏移24字节)和第5列(偏移20字节)的标量积。若需求确实是第7列,需确认矩阵定义是否有误。 - 冗余变量简化:
var1和var2为不必要的中转,可直接在寄存器中完成乘法运算。
修正后的标量积代码片段:
; 修正后的列标量积计算 lea EBX, arr1 add EBX, 24 ; 第6列(从1计数),对应索引5(从0计数) lea ESI, arr1 add ESI, 20 ; 第5列(从1计数),对应索引4(从0计数) mov ECX, rowCnt LOOP3: mov EAX, [EBX] imul EAX, [ESI] ; 直接计算两个元素的乘积 add scalarProd, EAX add EBX, 24 ; 跳至下一行同列 add ESI, 24 loop LOOP3
三、行元素统计部分错误
- 条件判断逻辑错误:需求是
a[i] <= -22 || a[i] > 81,但代码中判断a[i] > 81时用了jl C2(小于则跳转),导致a[i] >=81都会被统计,不符合要求,应改为jg C2(大于则跳转,不大于则跳过赋值)。 - 冗余变量处理:
check未被使用,可删除。
修正后的行统计代码片段:
; 修正后的第4行元素统计 lea EBX, arr1 add EBX, 72 ; 第4行起始偏移(前3行共3*6*4=72字节) mov ECX, 6 LOOP4: mov compRes, 0 mov EAX, [EBX] CMP EAX, varb ; varb=-22 jg C1 mov compRes, 1 C1: CMP EAX, varc ; varc=81 jg C2 ; 仅当EAX>81时,设置compRes=1 mov compRes, 1 C2: cmp compRes, 1 jne C3 inc condCnt mov EAX, condSum add EAX, [EBX] mov condSum, EAX C3: add EBX, 4 loop LOOP4
内容的提问来源于stack exchange,提问作者Roman Soroka
相关产品推荐
相关产品推荐

