大杰哥 發表於 2023-1-4 16:03:00

汇编语言的学习

<h2>寄存器</h2>
<p>在DOSBox里面有ax,bx,cx,dx,sp,ip,ds,之类的,如下图</p>
<p><img alt="" height="171" src="https://img-blog.csdnimg.cn/1ac8a81b4e604e8fbd5f356788ec50cb.png" width="1085"></p>
<p>&nbsp;寄存器的种类</p>
<p></p>
<p>可以分为数据类和指令类</p>
<p>AX(AH、AL):累加器</p>
<p>BX(BH、BL):基址寄存器</p>
<p>CX(CH、CL):计数寄存器</p>
<p>DX(DH、DL):数据寄存器 //不过这些都可以修改,一般就数据和指令。</p>
<h3>指令</h3>
<p>指令的选择是通过cs:ip来选择的。</p>
<p>其中cs代表段地址,ip代表偏移地址</p>
<p>选择该地址内容的数据做为指令。例如:</p>
<p><img alt="" height="545" src="https://img-blog.csdnimg.cn/3aec35b1657445089d78fdb3b55457d8.png" width="1061"></p>
<p></p>
<h3>数据</h3>
<p>数据的选择是通过ds:偏移量来确定的,例如:</p>
<p><img alt="" height="363" src="https://img-blog.csdnimg.cn/054822384aaa47c29d64db50a2429617.png" width="1077">&nbsp;这里我修改了ds的值,让ds指向1000的地址,在将ax赋值1000:0000地址的值</p>
<p><img alt="" height="165" src="https://img-blog.csdnimg.cn/1193bfeefa97442ea3b5eabd785d9420.png" width="1086"></p>
<p>&nbsp;从这里就可以知道了,数据的选择是ds决定的。</p>
<p></p>
<p></p>
<h2>段地址*10H +偏移地址=物理地址</h2>
<p><img alt="" height="505" src="https://img-blog.csdnimg.cn/5893f52c7bee4a5f8d02141d1afff427.png" width="1042"></p>
<p>&nbsp;这里可以看到,这两块的地址是一模一样的,类似于:2000+2000和4000的内容是一模一样的,地址含义也一样</p>
<p></p>
<p>我一般认为是绝对地址和相对地址。就比如说这个,1*10H+0=10H,所以绝对地址是0000:0010,而0001就是段地址,0001:0000就是相对地址,有什么问题可以发出来。</p>
<h2>call指令</h2>
<p>call指令的作用,就是跳转,但是和jmp的区别是会将下一条指令的ip存到栈中</p>
<p>后面使用ret指令回来(将ip修改回来)</p>
<p><img alt="" height="404" src="https://img-blog.csdnimg.cn/afabdffef6d24a94a2328f6891372de6.png" width="1082"></p>
<p>&nbsp;</p>
<p>这里是运行了call指令,原先ip=100,后面栈中存放下一条指令也就是103。</p>
<p><img alt="" height="213" src="https://img-blog.csdnimg.cn/64269658fc0449959d41e209a17bfc7b.png" width="1040"></p>
<p>&nbsp;这里用了ret,将ip修改回来了(通过栈)</p>
<p></p>
<h2>栈</h2>
<p>汇编里面的栈是通过ss:sp来指向的,用这里面的内存来存储数据</p>
<p>栈是先进后出,每次加进来的都要在标记的前面。</p>
<p>在这里面的内存形式0000:0000-------&gt;ffff:ffff ,所以每次入栈(push)sp=sp-2,而每次出栈就是(pop)sp=sp+2</p>
<p>栈的最大内存是sp=0时,因为sp=0-2=fffh,所以sp=0时栈内存最大</p>
<p>栈的内存表示,sp的起始到sp被我修改的值,其实是人为的认为,最常见认为sp的起始为0,sp的终止是10h,所以栈内存为10H</p>
<p>具体格式:push ax //是将ax里面的值存入ss:sp内存中</p>
<p>pop bx //是将栈里面的内容存入到bx寄存器中</p>
<p>类似的。</p>
<h2>psp区</h2>
<p>开始的256个字节是psp区,其作用是为了程序与系统进行通信的</p>
<p><img alt="" height="255" src="https://img-blog.csdnimg.cn/755bf87535914d4e9de37cf466c11e57.png" width="1058"></p>
<p>&nbsp;ds是取数据的,ds:0的数据并不是我写的程序的数据,一直到ds:0100才是,所以开始的256个字节是系统与程序进行通信的</p>
<p></p>
<p></p>
<p><img alt="" height="503" src="https://img-blog.csdnimg.cn/53b4593315a644ea9b8ed76972c8277e.png" width="1070">&nbsp;<img alt="" height="525" src="https://img-blog.csdnimg.cn/e719f684fcab4dc08aeb9acf89564100.png" width="763"></p>
<p>&nbsp;一个标准的asm(汇编)文件格式</p>
<p></p>
<pre>assume cs:code

code segment

&nbsp; &nbsp; &nbsp;mov ax,2000H &nbsp; ;在汇编语言中,;代表注释,mov代表赋值,add代表相加,pop出栈,push入栈,sub相减,jmp跳转,call
&nbsp; &nbsp; &nbsp;mov ss,ax &nbsp; &nbsp;;,号右边给左边,这个,号类似于等号
&nbsp; &nbsp; &nbsp;mov sp,0 &nbsp; &nbsp; &nbsp; ;等等
      add sp,10H &nbsp; &nbsp;
      pop ax
      pop bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
      push ax
      push bx &nbsp; ;交换ax,bx数据
&nbsp; &nbsp; &nbsp;pop ax
      pop bx
   &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;inc为增加的英文,inc bx,就是将bx加1,为了节约内存

      mov ax,4C00H;程序返回
      int 21H

code ends

end</pre>
<h2>loop循环以及用jmp实现类型loop</h2>
<p>loop比jmp多了一个次数操作,用cx来保存次数</p>
<p>jmp可以实现跳转</p>
<p>-p 可以直接执行完loop指令</p>
<p>-g 类似于go 后面要加地址</p>
<p><img alt="" height="651" src="https://img-blog.csdnimg.cn/bb6e06653b664494a668414b978f1944.png" width="1008"></p>
<p>&nbsp;loop也可以实现,但是loop需要注意的是cx=1,和cx=0的情况</p>
<p></p>
<p>cx=0时,会出现溢出。</p>
<p><img alt="" height="365" src="https://img-blog.csdnimg.cn/e375a80a71af45cfa62ae627a6ba8dfd.png" width="1030"></p>
<p>&nbsp;当cx=1时,可以看出并没有循环,原因是走了一遍就算循环了一次,当cx=0时跳出循环,如果还没有走cx已经为0了,cx-1=FFFF,就要循环FFFF次。</p>
<p><img alt="" height="250" src="https://img-blog.csdnimg.cn/3c3f5e9c6a5f4daba05d43a4b9100125.png" width="1063"></p>
<p>&nbsp;</p>
<p></p>
<p></p>
<h3>用汇编指令写234*145</h3>
<pre>assume cs:code
code segment


&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ax,0
   &nbsp; &nbsp; &nbsp;mov cx,145
addnumber:add ax,234 &nbsp; &nbsp;;jmp也是和loop一个格式,除开cx次数
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;loop addnumber
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ax,4C00H
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int 21H

code ends

end</pre>
<p></p>
<p><img alt="" height="244" src="https://img-blog.csdnimg.cn/f9fc94045b1f4f62aa273f138649035f.png" width="993"></p>
<p><img alt="" height="278" src="https://img-blog.csdnimg.cn/2684323a930e462c90c67cb1e159bb51.png" width="398">&nbsp;</p>
<p>debug的缺陷:有英文字母开头时,前面要加0</p>
<p></p>
<p>比如:mov ax,0ffffH</p>
<p>不加H时表示十进制。</p>
<h3>通过es和ds数据寄存器来交换数据实操</h3>
<pre>assume cs:code
code segment


&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ax,0fffH
   &nbsp; &nbsp; &nbsp;mov ds,ax
   &nbsp; &nbsp; &nbsp;mov ax,2000H
   &nbsp; &nbsp; &nbsp;mov es,ax

   &nbsp; &nbsp; &nbsp;mov cx,10H
   &nbsp; &nbsp; &nbsp;mov bx,0
adderten: &nbsp; mov al,ds:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov es:,al;es:是一个字节数据类型,不是字型数据类型
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc bx
   &nbsp; &nbsp; &nbsp;loop adderten


mov ax,4C00H
int 21H

code ends

end</pre>
<h3>通过栈来复制两个地方的数据</h3>
<pre>assume cs:code
code segment
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov bx,0
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov cx,10H
adderten: &nbsp; mov ax,0fffH
   &nbsp; &nbsp; &nbsp;mov ds,ax
   &nbsp; &nbsp; &nbsp;mov ax,0
   &nbsp; &nbsp; &nbsp;mov al,ds:
   &nbsp; &nbsp; &nbsp;push ax
   &nbsp; &nbsp; &nbsp;mov ax,2000H
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ds,ax
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop ds:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc bx
   &nbsp; &nbsp; &nbsp;loop adderten


mov ax,4C00H
int 21H

code ends

end</pre>
<h3>dw 操作数据</h3>
<pre>assume cs:code
code segment

&nbsp; &nbsp;dw 1,2,3,4,5,6,7,8,9
start:
&nbsp; &nbsp; &nbsp; mov ax,0
&nbsp; &nbsp; &nbsp; mov bx,0
addax: add ax,cs: &nbsp; ;start 指定操作开始的位置
&nbsp; &nbsp; &nbsp; add bx,2 &nbsp; &nbsp; &nbsp; &nbsp; ;不用start在开头用jmp指令也行
&nbsp; &nbsp; &nbsp; loop addax &nbsp; &nbsp;

mov ax,4C00H
int 21H

code ends

end &nbsp;start</pre>
<p><img alt="" height="264" src="https://img-blog.csdnimg.cn/bad029d413fe42de827b98d4d041f103.png" width="1050"></p>
<p>&nbsp;</p>
<h3>dw和栈联用</h3>
<pre>assume cs:code
code segment


&nbsp; &nbsp;dw 1122H,2233H,3344H,4455H,5566H,6677H,7788H,8899H,9900H
&nbsp; &nbsp;dw 0,0,0,0,0,0,0,0
&nbsp; &nbsp;dw 0,0,0,0,0,0,0,0
start:
&nbsp; &nbsp; &nbsp; &nbsp; mov ax,cs
&nbsp; &nbsp; &nbsp; &nbsp; mov ss,ax
&nbsp; &nbsp; &nbsp; &nbsp; mov sp,32H &nbsp; &nbsp; ;栈内存是看字节形数据,所以应该是32H
&nbsp; &nbsp; &nbsp; &nbsp; mov bx,0
&nbsp; &nbsp; &nbsp; &nbsp; mov cx,9
addax: &nbsp; push cs:
&nbsp; &nbsp; &nbsp; &nbsp; add bx,2
&nbsp; &nbsp; &nbsp; &nbsp; loop addax

mov ax,4C00H
int 21H

code ends

end &nbsp;start</pre>
<p><img alt="" height="330" src="https://img-blog.csdnimg.cn/e37f04cb9e724aaea16ee61740f07b51.png" width="954"></p>
<p>&nbsp;</p>
<h3>数据段,指令段,stack段</h3>
<p>这样写可能会出一个bug,就是设置sp的大小就一定要和栈段一致,不然就会执行不知道什么的指令,那个时候就是严重型bug</p>
<pre>assume cs:code,ds:data,ss:stack
data segment
&nbsp; &nbsp;dw 1122H,2233H,3344H,4455H,5566H,6677H,7788H,8899H,9900H

data ends

stack segment
&nbsp; &nbsp;dw 0,0,0,0,0,0,0,0
&nbsp; &nbsp;dw 0,0,0,0,0,0,0,0
stack ends

code segment

start:
&nbsp; &nbsp;mov ax,stack &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;mov ss,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;设置栈
&nbsp; &nbsp;mov sp,32 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;如果这样写了,设置栈的大小就一定要和栈段里面的要一致
&nbsp; &nbsp;mov ax,data &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp;mov ds,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;设置数据段
&nbsp; &nbsp;mov bx,0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;这样做就会将ds寄存器当作数据,ss:sp数据当作栈。
&nbsp; &nbsp;mov cx,9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
addax:push data:
&nbsp; &nbsp; &nbsp; add bx,2
&nbsp; &nbsp;loop addax

mov ax,4C00H
int 21H

code ends

end &nbsp;start
​</pre>
<h4>段的位置</h4>
<p>第一段一般是数据,第二段一般是栈,第三段则是指令</p>
<p>第一和第二段可以换位置,但是第三段不能换,涉及到数据覆盖问题</p>
<p>数据段位置:</p>
<p><img alt="" height="86" src="https://img-blog.csdnimg.cn/b454efeb5f414eac908fb6ce437c9d2e.png" width="1035">&nbsp;</p>
<p></p>
<p>栈段位置:</p>
<p><img alt="" height="82" src="https://img-blog.csdnimg.cn/c63df65e0dfb4891a276ebaf4327ba80.png" width="797">&nbsp;</p>
<p></p>
<p>指令段:</p>
<p><img alt="" height="72" src="https://img-blog.csdnimg.cn/a260c9999dcf40e885f6c7c15d7140c8.png" width="832">&nbsp;</p>
<p></p>
<h4>段的空间大小</h4>
<p><img alt="" height="84" src="https://img-blog.csdnimg.cn/296401c1aef1449cb0fb798413fdbb4e.png" width="941"></p>
<p></p>
<p>就是16的倍数,如果比如9个字节长度,大小就是16个字节,如果说是23个字节长度,大小就是32个字节。</p>
<p>向大号取整。</p>
<p>比如说这个例子:就是数据是9个字型性长度,所以用了32个字节型长度。</p>
<h4>段的练习1:将两个数据段的数据相加,放到另外一个段中</h4>
<pre>assume cs:code
a segment
&nbsp; &nbsp;db 1,2,3,4,5,6,7,8

a ends

b segment
&nbsp; &nbsp;db 1,2,3,4,5,6,7,8 &nbsp; &nbsp; ;因为数据段寄存器不够了,所以先用栈保存一下位置,然后直接修改es寄存器将es寄存器改成c段那边,然 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;后赋值,后面pop掉es,就行了
b ends
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
c segment
&nbsp; &nbsp;db 0,0,0,0,0,0,0,0
c ends


code segment

start:
&nbsp; &nbsp; &nbsp; mov ax,a
&nbsp; &nbsp; &nbsp; mov ds,ax
&nbsp; &nbsp; &nbsp; mov cx,8
&nbsp; &nbsp; &nbsp; mov ax,b
&nbsp; &nbsp; &nbsp; mov es,ax
&nbsp; &nbsp; &nbsp; mov bx,0
&nbsp; &nbsp; &nbsp; mov ax,0
addax: push es
&nbsp; &nbsp; &nbsp; mov ax,ds:
&nbsp; &nbsp; &nbsp; add ax,es:
&nbsp; &nbsp; &nbsp; mov dx,c
&nbsp; &nbsp; &nbsp; mov es,dx
&nbsp; &nbsp; &nbsp; mov es:,ax
&nbsp; &nbsp; &nbsp; inc bx
&nbsp; &nbsp; &nbsp; pop es
&nbsp; &nbsp; &nbsp; loop addax
&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; mov ax,4C00H
&nbsp; &nbsp; &nbsp; int 21H

&nbsp; &nbsp;code ends

&nbsp; &nbsp; &nbsp; end &nbsp;start
​</pre>
<p>&nbsp;</p>
<p></p>
<h4>段的练习2:将a段中的前8个字型数据,逆序复制到b段中</h4>
<pre>assume cs:code
a segment
&nbsp; &nbsp;dW 1,2,3,4,5,6,7,8,0AH,0BH,0CH,0DH,0FH,0FFH

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,b
&nbsp; &nbsp; &nbsp; mov ss,ax
&nbsp; &nbsp; &nbsp; mov sp,16
&nbsp; &nbsp; &nbsp; mov ax,a
&nbsp; &nbsp; &nbsp; mov ds,ax
&nbsp; &nbsp; &nbsp; mov bx,0
&nbsp; &nbsp; &nbsp; mov cx,8
adder: push ds:
&nbsp; &nbsp; &nbsp; add bx,2
&nbsp; &nbsp; &nbsp; loop adder
&nbsp; &nbsp; &nbsp; mov ax,4C00H
&nbsp; &nbsp; &nbsp; int 21H

&nbsp; &nbsp;code ends

&nbsp; &nbsp; &nbsp; end &nbsp;start
​</pre>
<h2>bx,si,di都为偏移地址寄存器</h2>
<pre>assume cs:code
a segment
&nbsp; &nbsp;dW 1,2,3,4,5,6,7,8,0AH,0BH,0CH,0DH,0FH,0FFH

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,a
&nbsp; &nbsp; &nbsp; mov ds,ax
&nbsp; &nbsp; &nbsp; mov si,1
&nbsp; &nbsp; &nbsp; mov di,2
&nbsp; &nbsp; &nbsp; mov bx,0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; mov ax,ds: ;唯一的缺点就是不能用减法
&nbsp; &nbsp; &nbsp; add ax,ds:
&nbsp; &nbsp;code ends
end &nbsp;start</pre>
<h2>and,or运算符</h2>
<pre>assume cs:code
a segment
&nbsp; &nbsp;dW 1,2,3,4,5,6,7,8,0AH,0BH,0CH,0DH,0FH,0FFH

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,00001111B
&nbsp; &nbsp; &nbsp; and ax,11110000B
&nbsp; &nbsp;code ends
end &nbsp;start
​</pre>
<p>&nbsp;</p>
<p></p>
<pre>assume cs:code
a segment
&nbsp; &nbsp;dW 1,2,3,4,5,6,7,8,0AH,0BH,0CH,0DH,0FH,0FFH

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,00001111B
&nbsp; &nbsp; &nbsp; or ax,11110000B
&nbsp; &nbsp; &nbsp; mov ax,'a'
&nbsp; &nbsp; &nbsp; mov bx,'b'
&nbsp; &nbsp;code ends
end &nbsp;start
</pre>
<p><img alt="" height="321" src="https://img-blog.csdnimg.cn/732e7cf9ecb54727af89abc430ca1ffe.png" width="1080"></p>
<p>&nbsp;</p>
<p></p>
<h2>字符</h2>
<p><img alt="" height="570" src="https://img-blog.csdnimg.cn/d8f6f2b622c34bf2ac83dd03d2f925ff.png" width="1200"></p>
<p>&nbsp;</p>
<p><img alt="" height="513" src="https://img-blog.csdnimg.cn/30ede836cd8d45d98033ed5cb30bb40b.png" width="1200">&nbsp;</p>
<p>&nbsp;</p>
<p></p>
<p></p>
<h3>同个字母的大写字母比小写字母要小32</h3>
<h3>将数据段nihao中的i变成大写I</h3>
<pre>assume cs:code
a segment
&nbsp; &nbsp;db 'nihao,I am you '

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,a
&nbsp; &nbsp; &nbsp; mov ds,ax
&nbsp; &nbsp; &nbsp; mov bx,1
&nbsp; &nbsp; &nbsp; mov al,ds:
&nbsp; &nbsp; &nbsp; andal,11011111B;注意不能在数据段进行and or操作
&nbsp; &nbsp; &nbsp; mov ds:,al
&nbsp; &nbsp; &nbsp; mov ax,4C00H
&nbsp; &nbsp; &nbsp; int 21H
&nbsp; &nbsp;code ends
end &nbsp;start</pre>
<p><img alt="" height="74" src="https://img-blog.csdnimg.cn/40f9cf2fcd9f4f0c81ac20354ef28632.png" width="1047">&nbsp;</p>
<p></p>
<h3>将数据段中的所有数据变成大写</h3>
<pre>assume cs:code
a segment
&nbsp; &nbsp;db 'nihao,I am you '

a ends

b segment
&nbsp; &nbsp;dW 0,0,0,0,0,0,0,0
b ends

code segment

start: mov ax,a
&nbsp; &nbsp; &nbsp; mov ds,ax
&nbsp; &nbsp; &nbsp; mov bx,0
&nbsp; &nbsp; &nbsp; mov cx,14
adder: mov al,ds:
&nbsp; &nbsp; &nbsp; andal,11011111B
&nbsp; &nbsp; &nbsp; mov ds:,al
&nbsp; &nbsp; &nbsp; inc bx
&nbsp; &nbsp; &nbsp; loop adder
&nbsp; &nbsp; &nbsp; mov ax,4C00H
&nbsp; &nbsp; &nbsp; int 21H
&nbsp; &nbsp;code ends
end &nbsp;start
​&nbsp;</pre>
<p></p>
<p>使用si和di偏移地址寄存器</p>
<p></p>
<h2>后面持续更新</h2><br><br>
来源:https://www.cnblogs.com/nanshaws/p/17892502.html
頁: [1]
查看完整版本: 汇编语言的学习