汇编语言中的二维数组
Posted
技术标签:
【中文标题】汇编语言中的二维数组【英文标题】:2D Arrays in Asembly language 【发布时间】:2021-07-07 03:24:40 【问题描述】:我正在尝试将我的 C++ 代码转换为 MASM 代码。 我遇到了二维数组的问题。
请帮帮我!
问题:找出最长的公共子串
我的 C++ 代码:
#include<stdio.h>
#include<string.h>
char s[20],t[20];
int b[20][20];
int n,m;
void substr(int i,int j)
if (i&&j)
if (b[i][j]==1)
substr(i-1,j-1);
printf ("%c",s[i]);
else if (b[i][j]==2)
substr(i-1,j);
else substr(i,j-1);
int main()
int f[20][20];
gets(s+1);
gets(t+1);
m=strlen(s+1);
n=strlen(t+1);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
if (s[i]==t[j])
f[i][j]=f[i-1][j-1]+1;
b[i][j]=1;
else
if (f[i-1][j]>=f[i][j-1])
f[i][j]=f[i-1][j];
b[i][j]=2;
else
f[i][j]=f[i][j-1];
b[i][j]=3;
printf("\n::: OUTPUT :::\n");
if(n==0)
printf("There is no common substring of S and T!");
else
printf("The longest substring: \"");
substr(m,n);
printf("\".");
return 0;
还有我的 ASM 代码:
.model small
; input s, m is lenght of s
input macro s,m
push ax
push dx
mov ah, 0Ah
lea dx, s
int 21h
mov al, s + 1
xor ah, ah
mov m, ax
pop ax
pop dx
endM
substr macro i,j
push ax
push bx
push cx
if_s:
loopij:
cmp i,0
jne halt
cmp j,0
jne halt
if_2s:
cmp b[i][j],1
jne else_if
dec i
dec j
substr(i,j)
lea dx, s[i]
mov ah, 9
int 21h
jmp halt
else_ifs:
cmp b[i][j],2
jne else
dec i
substr(i,j)
jmp halt
elses:
dec j
substr(i,j)
jump halt
jmp loopij
ret
halt:
pop ax
pop bx
pop cx
endm
.stack 100h
.data
newline db 10,13, "$"
s db 255, ?, 255 dup(0)
t db 255, ?, 255 dup(0)
m dw ?
n dw ?
i dw ?
j dw ?
arr1 db i dup(0)
db j dup (0)
arr2 db i dup (0)
db j dup (0)
.code
main proc
mov ax,@data
mov ds,ax
input s, m
call newln
input t, n
call newln
xor ax, ax
inc ax
mov i, 2
loopi:
add ax, m
cmp i, ax
ja outloopi
mov j, 2
loopj:
mov ax, 1
add ax, n
cmp j, ax
ja outloopj
if_:
mov dx, s[i]
cmp dx, t[j]
jne else
mov cx, f[i-1][j-1]
mov f[i-1][j-1], cx
mov b[i][j],1
else:
else_if:
cmp f[i-1][j], f[i][j-1]
jb else_else
mov cx,f[i-1][j]
mov f[i][j], cx
mov b[i][j],2
else_else:
mov cx,f[i][j-1]
mov f[i][j], cx
mov b[i][j],3
jmp loopj
outloopj:
jmp loopi
outloopi:
substr m, n
mov ax,4ch
int 21h
main endp
newln proc
mov ah, 9
lea dx, newline
int 21h
ret
newln endp
end main
如何在 ASM 中声明二维数组?
如何在 ASM 中处理二维数组?
在这种情况下我可以将二维数组转换为一维数组吗?
非常感谢!
【问题讨论】:
内存是线性的(即 1d),所以我们总是必须将 2d 或更高的值转换为 1d。 @ErikEidt:如果您使用带有静态数组的 2 寄存器寻址模式,您可以将一个作为行首的字节偏移量,另一个作为是一行内的字节偏移量。但是,是的,您应该考虑线性字节,即使您为寻址模式的一部分使用单独的寄存器。 【参考方案1】:如何在 ASM 中声明二维数组? 如何在 ASM 中处理二维数组?
我们以 3 X 4 矩阵为例,即 3 行 4 列。
(0,0) (0,1) (0,2) (0,3) <- 1st row
(1,0) (1,1) (1,2) (1,3) <- 2nd row
(2,0) (2,1) (2,2) (2,3) <- 3rd row
^ ^ ^ ^
1st 2nd 3rd 4th
col col col col
假设元素是字节大小的,只需要写:
MyArray db 3*4 dup (0)
这会留出 12 字节的内存块。它作为二维数组的特殊性质纯粹来自程序员如何与它交互并解释它的内容。
以行顺序查看矩阵:
| MyArray
|
< row 0 > < row 1 > < row 2 >
----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
(0,0) (0,1) (0,2) (0,3) (1,0) (1,1) (1,2) (1,3) (2,0) (2,1) (2,2) (2,3)
以下是您如何寻址数组中的任何元素。
OffsetInTheArray = (RowIndex * NumberOfColumns + ColumnIndex) * BytesPerElement
emu8086 风格的赋值MyArray[Row][Col] = 1
:
mov ax, Cols ; CONST, (Cols equ ...)
mul Row
add ax, Col
;;;shl ax, 1 ; Only for word-sized elements
mov bx, ax
mov byte ptr MyArray[bx], 1
按列顺序查看矩阵:
| MyArray
|
< col 0 > < col 1 > < col 2 > < col 3 >
----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
(0,0) (1,0) (2,0) (0,1) (1,1) (2,1) (0,2) (1,2) (2,2) (0,3) (1,3) (2,3)
以下是您如何寻址数组中的任何元素。
OffsetInTheArray = (ColumnIndex * NumberOfRows + RowIndex) * BytesPerElement
emu8086 风格的赋值MyArray[Row][Col] = 1
:
mov ax, Rows ; CONST, (Rows equ ...)
mul Col
add ax, Row
;;;shl ax, 1 ; Only for word-sized elements
mov bx, ax
mov byte ptr MyArray[bx], 1
与二维数组的问题无关,但非常重要。
input macro s,m push ax push dx ... pop ax pop dx endM
您必须以相反的顺序恢复这些寄存器!堆栈是后进先出 (LIFO) 结构:
push ax
push dx
...
pop dx
pop ax
substr macro i,j push ax push bx push cx ... pop ax pop bx pop cx endm
您还必须以相反的顺序恢复这些寄存器。同样重要的是,看到 substr 是一个递归过程,你不应该把它变成一个宏。
cmp i,0 jne halt cmp j,0 jne halt
这个 sn-p 不是 if (i&&j)
的正确翻译。恰恰相反:
cmp i, 0
je halt
cmp j, 0
je halt
mov ax,4ch int 21h
DOS 功能号进入AH
寄存器。您的指令将其放入AL
。
mov ax, 4C00h ; DOS.TerminateWithReturnCode
int 21h
lea dx, s[i] mov ah, 9 int 21h
这不会像printf ("%c",s[i])
那样工作。 DOS.PrintString 函数 09h 期望 DX
指向以 $ 结尾的字符串。另一个 DOS 函数可以做到这一点:
mov bx, i
mov dl, s[bx+2]
mov ah, 02h ; DOS.PrintCharacter
int 21h
如果您想知道+2
,那么您已经通过使用 DOS.BufferedInput 函数 0Ah 获得了字符串 s,该函数从您的缓冲区返回偏移量 2 处的字符命名为s。您将不得不在许多地方注意这一点。
接下来是问题的快速解决方案:
db 255, 0
s db 255 dup (0)
...
lea dx, s-2
mov ah, 0Ah ; DOS.BufferedInput
int 21h
这段代码还有其他问题,但我认为通过以上所有内容,您应该能够编写第一次尝试。使用该代码,您可以随时返回...
【讨论】:
以上是关于汇编语言中的二维数组的主要内容,如果未能解决你的问题,请参考以下文章
嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)
嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)
嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)
嵌入式 ARM 汇编编程例题(二维数组按规律求和,求两数 gcd / lcm,求数组 min / max,字符串复制,排序)