我正在尝试将我的 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 中处理二维数组?
在这种情况下,我可以将二维数组转换为一维数组吗?
非常感谢!
答案 0 :(得分:1)
如何在 ASM 中声明一个二维数组?
如何在 ASM 中处理二维数组?
让我们以 3 X 4 矩阵为例,即 3 行 x 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
此代码段不是 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
此代码中还有其他问题,但我认为通过上述所有内容,您应该能够编写第一次尝试。使用该代码,您可以随时返回...