assembly 组件8086中的堆叠和阵列

mec1mxoz  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(110)
data segment
     S db 20 dup('$')
     T db 'true$'
     F db 'false$'
     A db 'Wabbit$'
     
     
ends

stack segment
    dw   128  dup(0)   
    pile:
    
ends

code segment
start:

    mov ax, data
    mov ds, ax
    mov es, ax
  mov dx,offset S
  mov ah,10
  int 21h
  mov cl,S[1]
  mov ch,0
  mov dx,offset S
  add dx,2 
  mov ah,9
  int 21h
    mov sp,pile
    mov si, 5 
    mov bp,sp
    
for1:    mov al,A[si]
         mov ah,0
         push ax
         dec si
         cmp si,0
         jge for1
         

  mov bp,sp
  add bp,12
  mov si,2 
  for:
      sub bp,2
      mov bx,[bp]
      mov ax,0
      mov al,S[si]
      mov ah,0
      cmp bx,ax
      jne exit
      inc si
      loop for
      mov dx , offset T
      mov ah,9
      int 21h
      jmp endd
      
 exit:
       mov dx,offset F
       mov ah,9
       int 21h
endd:
ends
end start
       
    

 
    mov ax, 4c00h ; exit to operating system.
    int 21h    
ends

end start ; set entry point and stop the assembler.

字符串
这是我的准则
这就是问题所在:
编写一个8086汇编程序,从用户处获取大小为20的字符串S,并确定S的内容是否在给定的单词堆栈(2个字节)的顶部找到,这些单词堆栈已经定义并填充了如下所示的值:
例如:假设S1=“Wabbit”由用户输入,堆栈的内容如上所述,程序将显示“True”,S2=“Exam”,程序将显示“False”。记住堆栈的内容总是固定的“Wabbit”,但是S的内容会改变。
我也有“假”,为什么?
我试着通过一步一步地运行来了解问题,所以当我第一次弹出时,我有74h的“W”的值,但是当我从字符串S中输入“W”的值时,它给出了57h。为什么?为什么?

pzfprimi

pzfprimi1#

S db 20 dup('$')
T db 'true$'
F db 'false$'

字符串

  • S* 缓冲区的定义错误。这是缓冲区溢出和内存损坏的公开邀请。第一个字节,应该通知DOS关于缓冲区的长度,在这里是36(ASCII表示'$')。所以DOS可以并且将会覆盖缓冲存储器中的“真”和“假”信息(部分)!

学会正确使用DOS.BufferedInput函数0Ah。在How buffered input works中阅读所有相关内容。

mov dx,offset S
add dx,2 
mov ah,9


DOS.PrintString函数09 h期望接收一个以$结尾的字符串。您 * 认为 * 通过预加载带有$ characters的缓冲区已经做到了这一点。不能保证一旦函数0Ah返回,这些$字符仍然存在。您应该始终显式地放置$字符。再次,请在How buffered input works中阅读相关内容。

mov bp,sp        <<<< first time
for1:
  mov al,A[si]
  mov ah,0
  push ax
  dec si
  cmp si,0
  jge for1
  mov bp,sp        <<<< second time
  add bp,12        <<<<  same value in BP

  • for 1 * 循环正确地将包含文本“Wabbit”的 A 字符串压入堆栈,但为什么要设置BP寄存器两次?您可以简单地忽略底部的mov bp, sp``add bp, 12行,但最好也删除顶部的mov bp, sp行,因为这是程序故障的根本原因。

您正在比较两个字符串,但对于输入的字符串,从第一个字符开始,对于堆叠的字符串,从最后一个字符开始。* 起点需要对应 *。
而且因为我看不出有什么好的理由首先在堆栈上push“Wabbit”字符串,只是像内存中的常规字符串一样遍历它(例如它在 A 处定义),我建议您pop字符以进行比较:

mov  dx, offset F
  mov  cl, S[1]       ; 1
  mov  ch, 0          ; 1
  cmp  cx, 6          ; 2
  jne  exit           ; 2
  mov  si, 2          ; We have same number of characters at SI as at SP
for:
  pop  ax
  cmp  al, S[si]
  jne  exit
  inc  si
  loop for            ; 1
  mov  dx , offset T
exit:
  mov  ah, 09h
  int  21h
  mov  ax, 4C00h
  int  21h

  1. loop指令取决于CX寄存器。别忘了提前初始化它。
    1.因为您将与已知长度为6个字符的固定字符串进行比较,所以如果输入字符串的长度不是6,则返回'false'是有意义的。
endd:
ends
end start
  mov ax, 4c00h ; exit to operating system.
  int 21h    
ends
end start


您不应该重复这些endsend start行!

fcy6dtqo

fcy6dtqo2#

看你的代码,我可以看到一些逻辑错误。需要理解的最重要的一点是,在使用pushpop时,x86的堆栈必须一次访问两个字节。没有push al,你必须使用push ax。您似乎理解这一点,这就是为什么您使用mov ah,0作为填充。
但是,最终用户不能将此填充放入他们键入的字符串中。因此,即使您在程序开始时输入“Wabbit”,您的程序也会尝试将db "Wabbit"db "W",0,"a",0,"b",0,"b",0,"i",0,"t",0进行比较,这就是为什么您会得到“false”作为答案。为了正确地比较两者,您需要将输入字符串转换为与测试字符串“Wabbit”存储在堆栈上类似的填充形式。
(Side注意:我之前给出的例子db "W",0,"a",0,"b",0,"b",0,"i",0,"t",0实际上可能是db 0,"W",0,"a",0,"b",0,"b",0,"i",0,"t",我不记得当你push ax时,alah在堆栈上的顺序是什么。如果一个不起作用,试试另一个。)

相关问题