汇编语言中的二维数组

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&amp;&amp;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,字符串复制,排序)