2017-09-26 113 views
0

我是x86-16位编程的新手。我非常难以正确地调用函数2来单独从字符串中读取字符。如果有人有任何想法,将不胜感激。下面的代码显示了我目前的尝试(其中之一)。在MS-DOS /程序集中将单个字符从字符串打印到标准输出中x86-16

.model small 
    .data 
     message db "Hello, DOS Here!", 0dh, 0ah 
    .code 
    main proc 
     mov ax, @data 
     mov ds, ax 
    L1: 
     mov ah, 2 
     mov bx, 1 
     int 21h 
     loop L1 

     .EXIT 
    main endp 
    end main 

我也应该使用push和pop来以相同的方法但是向后打印字符串。我确定我错过了一些明显的东西。我打印的时候得到的只是几行的英镑符号。 (Dec:156; Hex:9C)

+0

数你有机会获得一个调试器?第一步是了解它为什么要输出字符9C。调试器可以帮助解决这个问题。问问你自己是否每次都做同样的事情,以及它从哪里获得“9C”。 –

+2

请参阅[Ralf Brown中断列表](http://www.ctyme.com/intr/int-21.htm)。如果这看起来是一项家庭作业,那么正确的做法是刷完笔记并最终在办公时间访问。 :)你的代码显示了缺乏x86汇编语言的基础,我相信你不想在整个研究过程中拖动它。 –

+0

不知道你的意思是你的最新评论玛格丽特,但我正在尽我所能进一步了解我的材料。这只是我掌握的许多资源之一。就像生活中的其他事情一样,从各个角度得到建议总是很好的。你永远不知道谁有一招或两个袖子!感谢Moby的建议。我相信这将是处理这种语言的重要工具。它实际上是非常深入的(只要我已经阅读了足够的能够理解它......在这一点上工作)。 – Rifleman192

回答

1

根据这个定义message db "Hello, DOS Here!", 0dh, 0ah,接下来的代码将打印完整的消息:

mov ah, 02h 
mov dl, message  ;Get the H character 
int 21h 
mov dl, message+1 ;Get the e character 
int 21h 
mov dl, message+2 
int 21h 
mov dl, message+3 
int 21h 
mov dl, message+4 
int 21h 
mov dl, message+5 
int 21h 
mov dl, message+6 
int 21h 
mov dl, message+7 
int 21h 
mov dl, message+8 
int 21h 
mov dl, message+9 
int 21h 
mov dl, message+10 
int 21h 
mov dl, message+11 
int 21h 
mov dl, message+12 
int 21h 
mov dl, message+13 
int 21h 
mov dl, message+14 
int 21h 
mov dl, message+15 
int 21h 
mov dl, message+16 ;Get the 0Dh carriage return 
int 21h 
mov dl, message+17 ;Get the 0Ah linefeed 
int 21h 

而是愚蠢,止跌”你说?
为了使用一个循环,并获得很多紧凑的代码,我们需要:

  1. 把你的邮件地址中的地址寄存器。您可以从SIDIBXBP中进行选择。我在下面的代码中选择了BX
  2. 在此地址读取一个字节。
  3. 用DOS输出字节。
  4. 递增地址寄存器中的指针。
  5. 通过检查您刚刚输出的换行符是否为所有文本重复步骤2,3,4,5。因为在你的文本中,这是最后一个字符。

一个版本的循环:

mov bx, OFFSET message ;1. 
Again: 
mov dl, [bx]   ;2. 
mov ah, 02h    ;3. 
int 21h 
inc bx     ;4. 
cmp dl, 0Ah    ;5. 
jne Again 

我也应该使用push和pop要能够打印字符串中的相同方法,但倒退。

为了实现你的这个下一个任务,你会放一个push dx在步骤2和3之间。然后写一个额外的循环来显示反转的字符串:

Again2: 
pop dx 
mov ah, 02h 
int 21h 
cmp dl, "H" 
jne Again2 

的陷阱在这里将这

  • 你不应该输出之前,其他(实际)字符换行和回车==>提示:在开始第二循环
  • 前做2个 pop小号
  • 你不能轻易认为“H”将只显示为文本的第一个字符==>提示:算push小号
+0

避免发布完整的代码解决方案作业问题。 –

1

警告:我几十年没有这样做了,我没有编译器在我面前可以做到这一点。这看起来像一个任务,所以我不会写代码,但我会指出你在正确的方向。

Int 21h function 2要求您设置dl等于您要输出的字符。这里不需要推送和弹出,因为DOS不使用栈来传递参数。首先,在循环之外,您希望将寄存器指向消息的地址,如:MOV si, message。然后,您需要从消息中取消引用单个字节并将其放入dl。这将需要使用间接地址表示法。然后你可以调用中断21h并写入字符。

至于循环,有几种方法来处理它。您可以使用计数器,其中cx是典型的寄存器,并使用LOOP语句或DECJNZ语句。或者你可以在字符串的末尾放置一个标记,并在你点击该标记时终止循环。空字符通常用于此目的。您还需要移动到字符串中的下一个字符。您可以通过添加一个索引或通过递增循环中每次迭代的寄存器值来实现。就像INC si

说了这么多,有一个更容易的方法,避免循环,但也许是作弊。看看interrupt 21h function 9

+0

是的,使用函数9会是'作弊',因为它是其他练习之一(这很容易)。我已经修改了我的代码,并从开始字符开始。我只需要弄清楚如何让它移动到字符串中的下一个字符而不是ascii表中的下一个字符。以下是修订: – Rifleman192

0

是的,使用函数9将是'作弊',因为它是其他练习之一(这是一个简单的练习)。我已经修改了我的代码,并从开始字符开始。我只需要弄清楚如何让它继续循环,以便继续读取字符串而不是任意停止。这里就是我这么远(它打印出H和15e中的):

 .model small 
    .data 
     message db "Hello, DOS Here!" 
    .code 
    main proc 
     mov ax, @data 
     mov ds, ax 

     mov ah, 2 
     mov cx, 16 
     mov dl, message 
    L1: 
     int 21h 
     mov dl, message + 1 
     loop L1 

     .EXIT 
    main endp 
    end main 
+1

了解间接寻址。 –

+0

此外,通过发布此答案,您可能会得到低投票。我建议将它作为您的问题编辑。 –

+0

感谢提示Moby。我是新来张贴在这里,所以我会记住未来。 – Rifleman192

相关问题