emu8086
answer哥推荐的一个工具,和dosbox一样是老古董,但是emu确实比较nb
简洁的编辑界面:
先进的后退一步执行功能:
mov ax,bx 与 mov ax,[bx]
前者是将bx中存的内容(地址或具体数据)传入ax中,后者是将ds:bx这块地址中的内容传给ax
mov [bx],ax
将ax这块寄存器中的内容(地址或数据)传入ds:bx这块地址的内容中
小总结:带[]的是指对应地址的内容,其中的寄存器里的数据必须是一块地址。不带的是指一个寄存器。
loop
1 | mov cx,10 |
一个很好理解的循环指令,每次循环到s,cx都会-1,相当于for循环里的i,cx-1之后若不为零,则向前转至s处执行。若为0则不跳转直接向下执行
标号s要在loop前面,循环执行的指令在标号和loop中间
g指令和p指令
在debug中,g IP
可以跳转到指定的IP,可以实现快速运行到指定IP位置,但并不是将中间的跳过,而是一路执行到该指令
如过想要一次执行完循环语句直接输入p指令即可完成循环
一些杂注意事项
在汇编源程序中,数据不能以字母开头,所以要在前面加0
段前缀
简单的一条指令:mov ax,[bx]
这里bx表示偏移地址,默认段地址位ds
加上段前缀:
1 | mov ax,ds:[bx] |
以上cs,ss,es,ds等明显指明段地址的指令称为“段前缀”
很好理解
define word
指令dw表示define word,作用是定义字型数据,其后直接写数据,几个数据之间用逗号隔开,每个数据占一个字的长度
dw定义的数据处于代码段的最开始,偏移地址为0,2,4…… 逐个加2
书本第125页图6.1中写DS = 0B2D
,而且程序dw了8个数据,那么真正的代码存放就从0B3D:0000
开始,因为8个数据每个数据占2个字节,一共16个字节相当于0010h,代码段的开头就被这些数据占用了,那么真正的代码就从0B3D:0000开始
start
start用于指明入口所在,告诉编译器从这里开始执行,结尾要加上end start告知结束,当然这里的end体现了一个新的功能,除了结束之外还显示出通知入口在何处的功能
在代码段中使用栈
这里我们自己在代码段中用内容为0的字型数据”搭建”一段栈空间
1 | dw 0123h,0234h,0345h,0456h,0567h,0678h,0789h,0abch |
这里用dw定义16个字型数据0,当作栈空间用。那么怎么把这一段内存当作栈空间呢?我们联想到之前学到过的一些指针,如果要把一段内存当成栈,那就肯定要有一个栈顶指针来指向这段内存的起点,于是我们将ss:sp指向数据0的起点。接下来进行的push,pop等操作就是直接将这一段内存当成一段栈来操作的。那么cs:[bx]指向的这一段的开头那8个数据就可以一次压入栈