Asembly 语言中的 2D 数组



我正在尝试将我的C++代码转换为MASM代码。 我在使用 2D 阵列时遇到了麻烦。

请帮帮我!

问题:查找最长的常见子字符串

我的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中使用2D阵列?

在这种情况下,我可以将二维数组转换为一维数组吗?

多谢!

如何在 ASM 中声明 2D 数组?
如何在 ASM 中使用 2D 数组?

让我们以 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

分配MyArray[Row][Col] = 1emu8086 样式:

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

分配MyArray[Row][Col] = 1emu8086 样式:

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

与有关2-D数组的问题无关,但仍然非常重要。

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

此代码段不是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获得了字符串s。缓冲输入函数 0Ah,它已从您命名为 s的缓冲区返回偏移量 2 处的字符。你将不得不在许多地方注意这一点。

接下来是问题的快速解决方案:

db      255, 0
s db      255 dup (0)
...
lea     dx, s-2
mov     ah, 0Ah   ; DOS.BufferedInput
int     21h

这段代码中还有其他问题,但我认为通过上述所有内容,您应该能够编写第一次尝试。有了这段代码,你总是可以回来的...

最新更新