缓冲区和循环和拉丁字符

时间:2016-11-18 12:39:33

标签: assembly x86

我有一个练习,我对此有一些疑问。我有一本书解释它,但我不明白他的意思。我在互联网上看,但我找不到我的一些问题或同样的我不能了解。练习是指用户收到一条消息,之后将用拉丁字符给键盘,并且在控制之后将保存在内存的一个区域上只有大写字母,小拉丁字符和空(空格)和句号(。)。区域将被保存为缓冲区并将为40字节。如果按“ENTER”或已完成40个字符,则启动完成。程序将查找是否为字符,如果它不是一个字符则会出现一个消息,将终止该程序。如果我们有写字符,如果有大写字符将被修改为小字符,如果有小字符将是capslocks.Cant修改句号和空格。我会做一个您的示例

提供文字:

  

在这里写点东西。

修改后的

将是:

  

wRITE SOMETHING HERE。

    TITLE EXERC_4 
CODE SEGMENT 
ASSUME CS:CODE, DS:INFORMS:ss
 START:  MOV AX,INFORMS 
MOV DS,AX  
call starting
 call changing 
MOV SI,0 
LEA DX,MESSAGE
 MOV AH,9 
INT 21H 
MOV CX, 
MOV AH,4CH 
INT 21H
AGAIN: 
MOV AH,1 
INT 21H 
CMP AL,13     ;i use  ASCII for  ENTER 
JE CHECK 
CMP AL,32;    ;' ' for SPACE 
 JE SAVE 
CMP AL,'.'    ; 46 control for full stop
 JE SAVE 
CMP AL,'A'
 JB AGAIN
 CMP AL,'Z'
 JBE SAVE   
 CMP AL,'a'
 JB AGAIN
 CMP AL,'z' 
JA AGAIN
 SAVE:
 MOV BUFFER[SI],AL 
INC SI 
CMP SI,40 
JB AGAIN 
CHECK:
 MOV CX,SI 
JCXZ EXIT     
 MOV SI,0
 LEA DX OUTPUT  
MOV AH,9 
INT 21H
 START_LOOP: 
 MOV DL,BUFFER[SI]
 CMP DL,32 
JE NEXT
 CMP DL,'.' 
JE NEXT 
CMP DL,'a' 
JB CAPSLOCKS 
SUB DL,32 
JMP NEXT
 CAPSLOCKS:

    ADD DL,32
 NEXT: 
MOV AH,2 
INT 21H
 INC SI
 LOOP START_LOOP 
 JMP END
 EXIT: 
LEA DX,MES_END 
MOV AH,9 
INT 21H
 END:
 MOV AH4CH 
 INT 21H
 CODE ENDS 
INFORMS SEGMENT 
 BUFFER 40DB dub(0)
 MESSAGE DB "GIVE ONE MESSAGE  :"
 INFORM ENDS 
END START

1 个答案:

答案 0 :(得分:0)

  

1)呼叫开始。这是什么以及何时停止?与改变

相同

它将在堆栈上推送以下指令的地址(call changing),并将ip的值更改为标签starting的地址。这意味着,CPU将从那里执行下一条指令,因为x86 CPU中的ip是"指令指针"。

当它停止时 - 技术上永远不会。有指令ret从堆栈中弹出值并将ip设置为它,可以看作"从呼叫返回"通过人工,但从CPU的角度来看,它只是改变ip的另一种时髦方式(所以jmp指令的另一种变体,只是更复杂的一种,从堆栈中获取目标地址并最终当使用ret #imm16变体时,更多地调整堆栈指针。

如果"在通话中"你更改了sp,或者损坏了堆栈中的返回地址,ret将无法按预期工作,因为CPU不知道是"内部有一个呼叫",它&#39 ;只需执行cs:ip的指令 - 无论你指向哪里。

所以"当它停止" - >你掌握在"开始:"代码,你必须希望它以最终正确返回到call starting之后的下一条指令的方式编写,你在堆栈顶部给它那个地址,但既然你有不再受控制,starting:的代码是。

顺便说一下,堆栈只是sp寄存器指向的普通内存,它不是什么神奇的东西,所以如果你把太多的东西放进去,你就可以很容易地用完这个空间,或者你可以去如果您未正确配对sp说明,则与push/pop值不同步。或者你可以通过普通的方式覆盖堆栈内存,如果你以某种方式错误地计算你的修改地址,你甚至会意外地改变任何其他内存。

  

2)MOV AH,4CH。为什么它只有4?为什么CH背后呢?

在评论中回答。了解什么是十六进制数,以及如何将它们转换为十进制数。

您可能也想知道为什么汇编程序员经常使用十六进制格式。主要原因是,每个十六进制数字恰好由4位组成。因此,当您使用位掩码时,我可以立即从字节值37h告知设置了5位(以及哪些是:0011 0111)。如果您将小数格式的值显示为55,我将需要计算相当长的一段时间,然后才能在我的头脑中看到这个二进制形式。

另外,你可以用源文本大小固定的方式编写十六进制数字,即。 16b值为4位数:01234h(带前导0,因此对0BEEFh值也会保持固定大小... BEEFh将与汇编程序的标签混淆。那就是为什么我喜欢C / C ++ 0x前缀更多)

最后为什么4C是"终止" - >因为DOS供应商这么说。有关它的服务说明,请参阅int 21h文档。

  

3)JBE SAVE。我想保存它。

JBE代表"在低于或等于"时跳跃。查看任何docs

  

4)MOV BUFFER [SI],AL。不知道这个

     

5)JCXZ退出。从什么退出?

     

6)LOOP START_LOOP。这是什么循环?for,do,do-while?

好吧,我要在这里描述每条指令吗?我真的不想。

BUFFER[SI]是内存引用,因此AL中的值存储在地址(BUFFER + SI)的内存中。这与C数组语法array_var[index]类似,但您还必须记住CPU不知道您的数组元素大小,因此对于索引word(2个字节长)数组,您必须执行{{ 1}}或将索引值改为+ -2(因此它已经预先乘以)。

如果您阅读说明参考指南,并了解CPU的工作原理(基础知识),其他的应该是显而易见的。

  

7)MOV AH4CH。我的错误还是它?

它缺失","在" AH"之后。 [BUFFER + si*2]必须有两个参数分为",",然后" AH"看起来像寄存器名称,最后是" 4CH"是"终止" MOV的常量,紧跟在下一行,所以这是一个明显的拼写错误。