大家好,任何人都可以告诉我如何用 8086 汇编语言处理二维数组。我是汇编语言编程的初学者。谢谢
2 回答
Madhur 的链接几乎涵盖了它,您通读了吗?
例如,如果您已经了解 C 编程级别的 2d 数组,那么汇编程序是下一个合乎逻辑的步骤。
例如,使用 8 位字节数组 z[1][2] 是第二行第三项,如果你想这样想的话,计算它在 z 的 C 地址中的地址加上第一个索引时间数组的宽度,假设它是 13 字节宽,加上第二个索引,所以 &z + (13*1)+2 = &z+15;
使用伪代码而不是 x86 代码(如果这是家庭作业)。
;蛮力 ldr r0,=z ;将z的地址加载到r0中 移动 r1,#13 mul r1,#1 ;使它成为寄存器或从内存位置加载 mov r2,#2 ;使它成为寄存器或从内存位置加载 添加 r0,r1 添加 r0,r2 ldrb r1,[r0] ;读取字节 strb r3,[r0] ;写入字节 ;如果你的指令集允许寄存器偏移 ldr r0,=z ;将z的地址加载到r0中 移动 r1,#13 mul r1,#1 移动 r2,#2 添加 r1,r2 ldrb r4,[r0,r1] ;读取字节 strb r3,[r0,r1] ;写入字节 ; 或立即偏移量和偏移量是硬编码的 ldr r0,=z ;将z的地址加载到r0中 移动 r1,#13 mul r1,#1 添加 r0,r1 ldrb r4,[r1,#2] ;读取字节 strb r3,[r1,#2] ;写入字节
如果你在 C 中有循环
无符号字符 x[4][16]; 无符号字符 z[4][16]; 无符号整数 ra,rb; 对于(ra=0;ra<4;ra++) { 对于(rb=0;rb<16;rb++) { x[ra][rb]=z[ra][rb]; } }
转换为汇编程序非常简单。
ldr r0,=x ldr r1,=z mov r2,#0 ;ra 外: mov r3,#0 ;rb 内: mov r4,r2 lsl #2 ;16 字节宽 添加 r4,r3 ldrb r5,[r1,r4] strb r5,[r0,r4] 添加 r3,r3,#1 cmp r3,#16 内 添加 r2,r2,#1 cmp r2,#4 外层
蛮力将始终适用于每个平台,蛮力是基地址 +(宽度乘以第一个索引)+(第二个索引乘以元素的大小)。优化在很大程度上取决于您要执行的操作,例如,在我所做的第一个汇编示例中,如果第一个索引是硬编码的索引,则乘以 1 是愚蠢的,和/或将 #2 移动到寄存器是愚蠢的,如果那是一个硬编码的数字,只需加 2。如果计算一次与循环会更改要使用的最佳寄存器数量等想法,摆脱乘法,或其他技巧来摆脱如果乘法,如果你不能改变宽度并且你的平台没有或使乘法痛苦。
例如,具有某种寄存器偏移寻址 [r0,r1] 的平台,其中地址是两个寄存器的总和,可以为您节省一个加法并防止破坏基地址寄存器,以便您可以在循环中再次使用它。如果您想使用销毁指针 (*ptr++) 的指针样式,这可能会改变您实现循环的方式,某些平台允许您使用基址寄存器并向其添加值,例如 [r0], #16 将使用 r0 处的地址,然后在使用 r0 后将 16 添加到 r0,因此您不必刻录额外的添加指令……我认为 x86 没有,但它具有可用于此任务的其他功能。
从蛮力开始,作为 x86,这意味着您可能必须使用内存来保存循环变量,因为您可能没有足够的寄存器来执行任务(这没关系,因为 x86 有很多基于内存的指令),然后优化加载和存储变化的优势。
;This code grabs data bits from accumulator and outputs it to the carry
Main:
clr C
mov A, #00101010b;
call array;
jmp Main;
array:
subb A, #80H; mov can work here if you did not clr C
cpl A; check for proper array location
mov B, #8; set division factor
DIV AB; bit offset contained in B;
mov R6,B;
subb A, #30H; this bit will allow you to mov around the chosen register
cpl A;
mov R7, A;
mov A, @R7; this is the array position
inc R6;
loop:
rlc A; this takes the array bit to the carry for easy access
djnz R6, loop;