汇编程序设计王爽版分支
- 格式:pdf
- 大小:4.16 MB
- 文档页数:32
王爽《汇编语⾔》(第三版)实验10解析1、显⽰字符串assume cs:codedata segmentdb 'welcome to masm!',0data endscode segmentstart: mov dh,8mov dl,3mov cl,2mov ax,datamov ds,axmov si,0call show_strmov ax,4c00hint 21hshow_str: push dxpush cxpush si ; 保护⼦程序寄存器中⽤到的寄存器; 由于主程序的限定; 这⾥由CPU⾃动为我们分配栈空间mov di,0 ;显⽰缓存区中的偏移量mov bl,dhdec bl ; bl-1才是真正的⾏,因为⾏号从0开始计数mov al,160mul bl ; 每⾏160字节⽤⾏数*每⾏偏移量得到⽬标⾏的偏移量mov bx,ax ; mul bl之后,乘积存储在ax中,这⾥要转存⼊bx中mov al,2 ; 列的偏移量为2,两个字节代表⼀列!!!mul dl ; 与⾏偏移量同理add bl,al ;将列偏移量与⾏偏移量相加,得到指定位置的偏移量。
mov ax,0b800hmov es,ax ;指定显⽰缓存区的内存位置mov al,cl ; 由于后⾯jcxz语句的判断要⽤到cx,所以我们要将; cl(颜⾊)先存下来。
s: mov ch,0mov cl,ds:[si] ;⾸先将当前指向字符串的某个字符存⼊cx中jcxz ok ; 如果cx为0,则转移到ok标号执⾏相应代码mov es:[bx+di],cl ;将字符传⼊低地址mov es:[bx+di+1],al ; 将颜⾊传⼊⾼地址add di,2 ; 列偏移量为2inc si ; 字符串的偏移量为1loop s ; 不为0,继续复制ok: pop dxpop cxpop si ; 还原寄存器变量ret ; 结束⼦程序调⽤code endsend start2、解决除法溢出的问题这⾥要注意,把⼀个数放在了dx,⾼位寄存器中,那么就相当于65536。
汇编语言王爽第三版检测点答案带目录在学习汇编语言的过程中,王爽老师的《汇编语言(第三版)》无疑是一本备受推崇的经典教材。
而对于学习者来说,检测点的答案能够帮助我们更好地巩固知识,查漏补缺。
接下来,我将为大家详细呈现这本教材中各个章节检测点的答案,并附上清晰的目录,方便大家查阅和学习。
第一章基础知识检测点 11(1)1 个 CPU 的寻址能力为 8KB,那么它的地址总线的宽度为。
答案:13 位。
因为 8KB = 8×1024 = 2^13B,所以地址总线的宽度为 13 位。
检测点 12(1)8086 CPU 有根数据总线。
答案:16 根。
(2)8086 CPU 有根地址总线。
答案:20 根。
检测点 13(1)内存地址空间的大小受的位数决定。
答案:地址总线。
(2)8086 CPU 的地址总线宽度为 20 位,其可以寻址的内存空间为。
答案:1MB。
因为 2^20 = 1048576B = 1MB。
第二章寄存器检测点 21(1)写出每条汇编指令执行后相关寄存器中的值。
mov ax,62627 AX = 62627mov ah,31H AH = 31H,AX = 31627mov al,23H AL = 23H,AX = 3123H检测点 22(1)给定段地址为 0001H,仅通过变化偏移地址寻址,CPU 的寻址范围为到。
答案:00010H 到 1000FH。
(2)有一数据存放在内存 20000H 单元中,现给定段地址为 SA,若想用偏移地址寻到此单元。
则 SA 应满足的条件是:最小为,最大为。
答案:最小为 1001H,最大为 2000H。
第三章内存访问检测点 31(1)下面的程序实现依次用内存 0:0~0:15 单元中的内容改写程序中的数据。
完成程序。
assume cs:codesgcodesg segmentdw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987Hstart: mov ax,0mov ds,axmov bx,0mov cx,8s: mov ax,bxmov bx+16,axadd bx,2loop smov ax,4c00hint 21hcodesg endsend start检测点 32(1)下面的程序将“Mov ax,4c00h ”之前的指令复制到内存 0:200 处。
assume cs:code,ss:stack,ds:datastack segmentdw 16 dup (0)stack endsdata segmentdb 16 dup (0)db '1975','1976','1977','1978'db '1979','1980','1981','1982'db '1983','1984','1985','1986'db '1987','1988','1989','1990'db '1991','1992','1993','1994'db '1995'dd 16,22,382,1356dd 2390,8000,16000,24486dd 50065,97479,140417,197514dd 345980,590827,803530,1183000dd 1843000,2759000,3753000,4649000dd 5937000dw 3,7,9,13,28,38,130,220dw 476,778,1001,1442,2258,2793,4037,5635 dw 8226,11542,14430,15257,17800data endstable segmentdb 21 dup ('year summ ne ?? ')table endscode segmentstart:mov ax,stackmov ss,axmov sp,20hcall deal_data //处理数据call clean_disp //清屏call show_yearcall show_summcall show_necall show_wagemov ax,4c00hint 21hdeal_data:push dspush espush axpush bxpush cxpush sipush bpmov ax,datamov ds,axmov ax,tablemov es,axmov bp,0mov cx,21mov bx,0s0:mov si,0mov ax,10h[bx]mov es:[bp+si],axmov ax,64h[bx]mov es:5h[bp+si],axadd si,2add bx,2mov ax,10h[bx]mov es:[bp+si],axmov ax,64h[bx]mov es:5h[bp+si],axadd bx,2add bp,16loop s0mov bp,0mov cx,21mov bx,0s1:mov ax,0b8h[bx]mov es:0ah[bp],axmov cx,axmov ax,es:5h[bp]mov dx,es:7h[bp]call divdwmov es:0dh[bp],axpop cxadd bx,2add bp,16loop s1pop bppop sipop cxpop bxpop axpop espop dsretdivdw:push bx //除法运算:所需参数ax:被除数低16位dx:被除数高16位cx:16位除push si 数返回:ax:结果低16位dx:结果高16位cx:余数mov bx,axmov si,cxmov ax,dxmov dx,0div cxmov cx,axmov ax,bxdiv simov si,dxmov dx,cxmov cx,sipop sipop bxretshow_str:push ds //需要提供ds:显示字符所在内存的段si:第一个字符的偏移地址push es dh:显示字符所在行dl:第一个字符所在列cl:字符属性push axpush bxpush cxpush dipush simov ax,0b800h //显存初始段mov es,axmov al,0a0hmul dhmov bx,axmov dh,0add bx,dxadd bx,dxmov di,0mov dh,cldis:mov cl,[si]mov ch,0jcxz okmov dl,clmov es:[bx+di],dxinc siadd di,2jmp short disok:pop sipop dipop dxpop cxpop bxpop axpop espop dsretclean_disp:push espush sipush cxmov cx,0b800hmov es,cxmov si,0mov cx,4e20hs2:mov word ptr es:[si],0020hadd si,2loop s2pop cxpop sipop esretreset:push ds //输出缓冲区清零push cxpush simov cx,datamov ds,cxmov si,0mov cx,16s3:mov byte ptr [si],0inc siloop s3pop sipop cxpop dsretinverted_order:push ds //输出缓冲区字符顺序倒置push axpush cxpush sipush sppush bpmov cx,datamov ds,cxmov si,0mov cx,0mov ah,0mov bp,sps4: mov al,[si]mov cl,aljcxz ok_1push axinc sijmp short s4ok_1:mov si,0mov cx,0s5:mov cx,bpsub cx,spjcxz ok_2pop axmov [si],alinc sijmp short s5ok_2:pop bppop sppop sipop cxpop axpop dsretdtoc:push ax //数值转化成字符串push cxpush simov si,0s6:mov cx,0ahcall divdwadd cl,30hmov [si],clmov cx,axjcxz overinc sijmp short s6over: call inverted_orderpop sipop cxpop axretshow_value:push dspush bxpush cxpush dxpush sicall resetmov cx,datamov ds,cxcall dtocmov dh,bhmov dl,blmov cx,4mov si,0call show_strpop sipop dxpop cxpop bxpop dsretshow_year:push dspush axpush cxpush dxpush sipush dimov ax,tablemov ds,axmov cx,21mov si,0mov dh,1mov dl,1s7:mov byte ptr 4h[si],0push cxmov cl,4call show_strpop cxinc dhadd si,10hloop s7pop dipop sipop dxpop cxpop axpop dsretshow_summ:push dspush axpush bxpush cxpush dxpush simov ax,tablemov ds,axmov si,5hmov cx,21mov bh,1mov bl,10s8:mov ax,[si]mov dx,2h[si]call show_valueadd si,10hinc bhmov ax,tablemov ds,axloop s8pop sipop dxpop cxpop bxpop axpop dsretshow_ne:push dspush axpush bxpush cxpush dxpush simov ax,tablemov ds,axmov si,0ahmov cx,21mov bh,1mov bl,20s9:mov ax,[si]mov dx,0call show_valueadd si,10hinc bhmov ax,tablemov ds,axloop s9pop sipop dxpop cxpop bxpop axpop dsretshow_wage:push dspush axpush bxpush cxpush dxpush simov ax,tablemov ds,axmov si,0dhmov cx,21mov bh,1mov bl,30s10:mov ax,[si]mov dx,0call show_valueadd si,10hinc bhmov ax,tablemov ds,axloop s10pop sipop dxpop cxpop bxpop axpop dsretcode endsend start。
汇编语⾔-王爽前⾔学习汇编的两个最根本的⽬的:充分获得底层编程的体验,深刻理解机器运⾏程序的机理。
任何不以循序渐进的⽅式进⾏的学习,都将出现盲⽬探索和不成系统的情况,最终学习到的也⼤都是相对零散的知识,并不能建⽴起⼀个系统的知识结构。
⾮循序渐进的学习,也达不到循序渐进学习所能达到的深度,因为后者是步步深⼊的,每⼀步都以前⼀步为基础必须遵守的原则:①没有通过监测点不要向下学习②没有完成当前的实验不要向下学习③每⼀个实验都是后续内容的基础,实验的任务必须独⽴完成④本书的教学重⼼是:通过学习关键指令来深⼊理解机器⼯作的基本原理,培养底层编程意识和思想我们必须通过⼀定的编程实践,体验⼀个裸机的环境,在⼀个没有操作系统的环境中直接对硬件编程第1章基础知识汇编语⾔是直接在硬件之上⼯作的编程语⾔机器语⾔/机器指令集是机器指令的集合寄存器是CPU中可以存储数据的器件编译器能够将汇编指令转换成机器指令的翻译程序汇编语⾔由以下3类指令组成:1.汇编指令:机器码的助记符,由对应的机器码(核⼼) <汇编指令是机器指令便于记忆的书写格式>2.伪指令:没有对应的机器码,由编译器执⾏,计算机并不执⾏3.其他符号:+ - * /要想让⼀个CPU⼯作,就必须向它提供指令和数据。
指令和数据在存储器中存放,也就是我们平时所说的内存CPU要从内存中读数据,⾸先要指定存储单元的地址,CPU在读写数据时还要指明。
它要对哪个器件进⾏哪种操作所以CPU要想进⾏数据的读写,必须和外部器件进⾏下⾯3类信息的交互->存储单元的地址(地址信息)器件的选择,读或写的命令(控制信息)读或写的数据(数据信息)指令和数据没有任何区别,都是⼆进制信息。
CPU在⼯作的时候把有的信息看作数据,为同样的信息赋予了不同的意义1 Byte = 8 bit = 8个⼆进制位 = 8位⼆进制数据在计算机中专门有连接CPU和其他芯⽚的导线,通常称为总线,总线从逻辑上分为3类,地址总线、控制总线、数据总线(1)CPU通过地址线将地址信息3发出(2)CPU通过控制线发出内存读命令,选中存储器芯⽚并通知它将要从中读取数据(3)存储器将3号单元中的数据8通过数据线送⼊CPUCPU是通过地址总线来指定存储器单元的10根导线可以传送10位⼆进制数据。
⑴一个CPU的寻址能力为8KB,那么它的地址总线宽度为:13解析:1KB=1024B --> 8KB=8*1024B=23*210B=213B,也就是说,假设将每一个存储单元(1B=8bit)理解成一个房间,那么213B也就是说能找到213这么多个的房间数,房间编号从0--213-1 213就是CPU的寻址能力,也可以说是CPU寻址空间大小。
既然CPU能找到这么多种编号的房间,每一根线能传输0或者1也就是有213中可能,也就是说有13根地址总线,因此它的地址总线宽度为13。
假设将8KB改8Kb,1Kb = 1024 b,8kb = 1024 * 8 b=1024 Byte= 210=1024字节,所以地址总线宽度为10⑵1KB的存储器有1024个存储单元,存储单元的编号从0到1023解析:1个存储单元是8bit,即1Byte(字节),1字节就是一个存储单元,根据换算关系,1KB=1024B,即1KB有1024个存储单元,存储单元的编号都是从0开始编起,若有n根地址总线编号就从0到2n-1,假设地址总线有3根,那么能表示不同的标号情况有000,001,010,011,100,101,110,111。
即有这8种情况,对应的十进制为0-7。
(3)1KB的存储器可以存储1024*8个bit,1024个Byte解析:1B=8bit,1KB=1024B;那么1024B=1024*8bit(4)1GB、1MB、1KB分别是230220210个Byte解析:根据换算关系1GB=1024MB=1024*1024KB=1024*1024*1024Byte,1MB=1024KB=1024*1024Byte,1KB=1024B。
(5)8080、8088、80286、80386的地址总线宽度分别为16根,20根,24根、32根 ,则它们的寻址能力分别为:26(KB )、1(MB )、24(MB )、4(GB )解析:8080的寻址能力大小为216B ,转换为KB 就是26KB ,8088的寻址空间大小为220B=210KB=1MB ,80286的寻址能力为224B=214KB=24MB ,80386的寻址空间大小为232B=222KB=212MB=4GB(6)8080、8088、8086、80286、80386的数据总线宽度分别为8根、8根、16根、16根、32根,则它们一次可以传送的数据为1(B )、1(B )、2(B )、2(B )、4(B )解析:传送的数据可分为有符号和无符号的,如果是有符号的,那么最高位0代表在正数,为1代表负数。
AX=0008 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=0C1C ES=0C1C SS=0C1C CS=2000 IP=0005 NV UP EI PL NZ NA PO NC2000:0005 EBFC JMP 0003-tAX=0008 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000DS=0C1C ES=0C1C SS=0C1C CS=2000 IP=0003 NV UP EI PL NZ NA PO NC2000:0003 01C0 ADD AX,AX-q实验一查看CPU和内存,用机器指令和汇编指令编程(3) 查看内存中的内容PC主板上的ROM中有个一出产日期,在内存FFF00H-FFFFFH的某几个单元中,请找到这个出产日期并试图改变它。
Microsoft(R) Windows DOS(C)Copyright Microsoft Corp 1990-2001.C:\DOCUME~1\ADMINI~1>debug-d ffff:0 fFFFF:0000 EA 5B E0 00 F0 31 32 2F-32 35 2F 30 37 00 FC 59 .[...12/25/07..Y-q地址C0000~FFFFF的内存单元为只读存储器,写入数据操作是无效的。
因此出产日期无法改变。
下面内容摘自于网上还有另一种情况,如果你发现你能修改ROM中的生产日期,那么原因如下:每个计算机的结构都不一样,教材考虑的是普通8086PC机上的效果,个别计算机的效果可能不同。
也就是说在你的计算机中这个内存是可修改的所以,认为所有的计算机某些地址的内存不能修改是片面的。
书上说rom是只读的你就不去验证了吗?如何验证呢?我觉得这个实验最大的好处不是让我们验证了这个知识点,而是提醒我们要有怀疑的精神,怀疑之后再去验证才能跟深刻的理解知识,提升自己的能力,甚至还会发现有些书上描述的不准确甚至错误的地方。
学_汇编语⾔_王爽版要点采集笔记(未完待续...)第⼀章基础知识存储器(内存)存放CPU⼯作的指令和数据(CPU可以直接使⽤的信息在内存中存放);指令和数据都是⼆进制数没有任何区别,由CPU决定是数据还是指令内存单元:存储器被分为若⼲个存储单元,并从0开始编号(存储单元的地址),⼀个存储单元为1字节(8bit)CPU的读写总线逻辑上分为:地址总线、数据总线、控制总线地址总线:地址线宽度决定了CPU的寻址能⼒,计算⽅式:2^[地址线宽](个内存单元)数据总线:决定了CPU和外界的数据传输速度(8根数据总线可传送⼀个8位(bit)⼆进制数,即1个字节)控制总线:是各外部器件的不同控制线的集合CPU进⾏数据读写必须经过3类信息交互:①存储单元的地址(地址信息)②器件的选择,读或写的命令(控制信息)③读或写的数据(数据信息)读:CPU在内存中读取数据时,要先指定存储单元的地址(你要找⼀个地⽅先要确定⼀个地址),会把要读取的地址经过地址总线发给内存;同时CPU控制器将内存读命令通过控制总线发送给内存,并通知内存要读取数据;最后内存将被指定的内存单元中的数据经过数据总线送⼊CPU写:与读类似,CPU经地址线发送要操作的内存单元的地址,CPU经控制线将内存写命令发送⾄内存,并通知内存要写⼊数据;CPU通过数据线将数据送⼊指定的内存单元;内存地址空间:每⼀个外部器件都有⾃⼰的存储芯⽚(如显卡有显存RAM和ROM(装有显卡BIOS)、⽹卡ROM(装有⽹卡BIOS)),CPU控制各个设备都是通过总线向各个设备的存储芯⽚发送命令,存储芯⽚根据CPU的命令控制外设进⾏⼯作所有的物理存储器被看作⼀个由若⼲存储单元组成的逻辑存储器,每个物理内存在这个逻辑内存中占有⼀个地址段,即⼀段地址空间可看出各存储芯⽚都和CPU的总线相连;CPU对它们的读写都通过控制线发出内存读写命令CPU根据读取不同的地址实现对不同设备的读写操作,这个逻辑存储器就是内存地址空间,它的容量受CPU寻址能⼒的限制(即地址总线宽度限制),如有20位的地址总线宽度,它的寻址能⼒为2^20个内存单元(⼀个存储单元为1字节(8位))所以该CPU的内存地址空间的⼤⼩为1MB;32位地址线宽的CPU内存地址空间最⼤为为4GB(CPU不⾏的话加内存条也没得⽤!64位的就不得了了,主板不够插)1、CPU寻址能⼒ = 2^线宽2、⼀根数据总线传⼀位数据,8根数据总线⼀次传8位数据(1Byte)第⼆章寄存器CPU组成:运算器(信息处理)、控制器(控制各种器件进⾏⼯作)、寄存器(信息存储)内部总线实现CPU内部器件的联系外部总线实现CPU与主板和其他器件的联系AX、BX、CX、DX通常⽤来存放⼀般性数据——通⽤寄存器(后⾯是X的寄存器是16位的,现在的EAX前⾯加了个E是32位)这四个寄存器都可以分为两个独⽴的⼋位寄存器使⽤(如AX可分为⾼位AH和低位AL),是为了向下兼容(只使⽤低位,⾼位填0)单独使⽤时当成⼀个来看,同时使⽤时是整体(计算⽅法 2^[位数] )⼀个字=两个字节=>⼀个⼗六进制数,所以⼗六进制数的⼀位相当于⼆进制数的四位汇编指令不分⼤⼩写16位结构的CPU具备以下特征(64位同理):1、运算器⼀次最多可以处理16位的数据;2、寄存器的最⼤宽度为16位;3、寄存器和运算器之间的通路是16位的;8086CPU给出物理地址的⽅法:8086有20位地址总线,可传送20位地址,寻址能⼒为2^20 = 1M,⽽8086内部为16位结构,他只能传送16位的地址,表现出的寻址能⼒只有64,说明CPU不能直接传送16位数据地址到20位的总线上(资源浪费),所以需要转换成20位的地址;8086采⽤⼀种在内部⽤两个16位地址合成的⽅法来形成⼀个20位的物理地址(段地址和偏移地址),经过地址加法器转换成20位的物理地址,⽰意图:地址加法器的⼯作原理:物理地址 = 段地址SA*16+偏移地址EA & 物理地址 = 基础地址 + 偏移地址相当于把段地址往⾼位进了⼀位,这⾥说的16位是⼆进制的数,CPU中存储的数据只能是⼆进制,⽽我们表⽰地址是⽤16位的数字,前⾯说了2和16进制的转换关系,⼀个⼗六进制数的位等于四个位的⼆进制数,所以段地址乘以16,把段地址后移了⼀位,增加了⼀位16进制数,⼆进制就得加四位,即数据左移四位(⼆进制位),16+4=20位,转换完成⼀个数据的X进制形式左移1位,相当于乘以X(⼗进制数乘⼗后左移⼀位)⼀个数据的⼆进制形式左移N位,相当于该数据乘以2的N次⽅段落的概念:内存本⾝并没有被分段,分段概念来⾃于CPU,8086CPU⽤物理地址 = 段地址*16+偏移地址的⽅式给出内存单元的物理地址,使得我们可以⽤分段的⽅式来管理内存⽤段地址x16 定位段的起始地址,⽤偏移地址定位段中的内存单元注意:1、段地址X16必然是16的倍数,即⼀个段的起始地址也⼀定是16的倍数2、偏移地址为16位,16位地址的寻址能⼒为64k,所以⼀个段的长度最⼤为64kCPU访问内存单元时必须向内存提供内存单元的物理地址(有地址才知道要访问哪⾥)CPU可以⽤不同的段地址和偏移地址形成同⼀个物理地址(段地址+偏移地址都等于物理地址)偏移地址EA为16位,变化范围0~FFFFH,仅⽤偏移地址来寻址最多可寻64k个内存单元(如段地址位1000H,那么CPU寻址范围为:10000H~1FFFFH储存单元的地址⽤段地址和偏移地址描述:数据在21F60中 a、数据存在内存2000:1F60单元中;b、数据存在内存的2000段中的1F60中;(可将地址连续、起始地址为16的倍数的⼀组内存单元定义为⼀个段)段寄存器:提供段地址,8086CPU有4个段寄存器:CS(代码(指令)段寄存器)、DS(数据段寄存器)、SS(堆栈stack段寄存器)、ES(附加段寄存器)CS和IP(指令指针寄存器)是8086CPU中最关键的寄存器,存放CPU当前要读取的指令的地址在任何时候,CPU将CS为指定(存放)指令的段地址(代码段⾸地址),IP指定(存放)指令的偏移地址(指令从哪处代码开始执⾏),CS和IP经过地址加法器加⼯后(通过输⼊输出控制电路)从地址总线指向内存单元读取指令,指令再通过数据总线(经过输⼊输出控制电路)传递给指令缓冲器,再到执⾏控制器,实现执⾏效果内存中被CPU执⾏过的代码必然被CS:IP指向过1. 从 CS : IP 指向内存单元读取指令,读取的指令进⼊指令缓冲器2. IP = IP + 所读取指令的长度,从⽽指向下⼀条(即所指向的指令执⾏完后接着运⾏接着的下⼀条指令)CPU加电启动或复位时,CS=FFFFH,IP=0000H,即CPU刚启动时读取并执⾏的第⼀条指令是FFFF0H修改CS、IP值的指令:转移指令 jmp1. 同时修改CS、IP的内容:jmp 段地址:偏移地址(例:jmp 2AE3:3)2. 只修改IP的内容:jmp 某⼀合法寄存器(jmp ax),⽤寄存器中的值修改IP代码段:根据需要,将⼀组内存单元定义为⼀个段:把长度<=64kb的⼀组代码存在⼀组地址连续、起始地址为16的倍数的内存单元中(个⼈理解为偏移地址需要16位的位置),这段内存⽤来存放代码,从⽽定义了⼀个代码段(代码段不能影响CPU来是否执⾏它,还是得看CS:IP所指向的内存单元中的内容为指令,代码段仅仅是⼀种编程格式)所以要将CS:IP指向所定义的代码段中的第⼀条指令的⾸地址debug命令:R 查看、改变CPU寄存器的内容(修改寄存器中的值:r [寄存器名])D 查看内存中的内容( d 段地址:偏移地址)E 改写内存中的内容U 将内存中的及其指令翻译成汇编指令T 执⾏⼀条机器指令A 以汇编指令的格式在内存中写⼊⼀条机器指令第三章寄存器(内存访问)字单元:存放字型数据的内存单元⼀个字等于两个字节,⼀个字节等于8⽐特,则⼀个字型数据有16位;因为有两个字节组成,字可分为⾼位和低位,图中0和1可组成⼀个字,1位⽐0位⾼,所以他们组成的字,⾼位是4E,低位是20即4E20(可以直接⽤字的起始地址描述它,如0地址字单元)任何两个地址连续的内存单元,可以将其看成⼀个内存字单元,⼀个为字低位字节单元,⼀个为字⾼位字节单元DS寄存器和 [address]DS寄存器:⽤来存放要要访问数据的段地址(⾸地址),配合 [ EA ] 使⽤,[ ] 说明操作的是⼀个内存单元,EA为偏移地址,段地址为DS中存放的地址数据段:将⼀组长度⼩于64k、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从⽽定义了⼀个数据段;具体操作时⽤ds存放数据段的段地址,在根据需要⽤相关指令访问数据段中的具体单元栈(stack):出⼊栈规则LIFO(后进先出)⼊栈:push 出栈:poppush 寄存器 pop 寄存器push 段寄存器 pop 段寄存器push 内存单元 pop 内存单元内存空间是如何被当做栈使⽤的:每执⾏⼀次⼊栈指令,都会将寄存器的内容放⼊栈顶单元的上⽅,此时段寄存器SS、寄存器SP就会存放栈顶的地址及偏移量,任何时候SS:SP都指向栈顶元素,执⾏push和pop时,CPU从SS和SP中获取段顶地址⼊栈时:SP=SP-2 (⼊栈时由⾼位往低位⾛)出栈时:SP=SP+2 (出栈时由低位往⾼位⾛)注意:⼊栈时的偏移量SP的取值要⽐当前栈最⾼位+1位(如要⼊栈⾄1000E~F(即栈最底部的字单元地址000E),SP值应⽐F⾼⼀位0010栈顶越界:需⾃⾏根据所安排的栈⼤⼩进⾏出⼊栈,避免⼊栈数据太多越界,也要避免空栈的时候继续出栈导致越界;越界会覆盖或修改掉可能是其他程序的内存数据或指令,需要注意!push执⾏时,CPU改变栈顶的指向,即SP=SP-2,再将数据传⼊SS:SP指向的字单元中;pop执⾏时,CPU先读取栈顶指向的字单元数据,再改变SP,即SP=SP+2;可见push、pop指令修改的只是SP,栈顶的变化范围为:0~FFFF栈操作机制:SS:SP指⽰栈顶;改变SP后写内存的⼊栈指令;读内存后改变SP的出栈指令Debug的 T 命令在执⾏修改寄存器SS的指令时,下⼀条指令也紧接着被执⾏(mov ss,ax ; mov ss,[0] ; pop ss)可⽤段寄存器表⽰内存单元的段地址:第四章汇编程序编写汇编源码----编译连接----可执⾏⽂件(包含由汇编指令翻译过来的机器码和源程序中定义的数据以及相关的描述信息,如程序⼤⼩,占⽤多少内存空间等)伪指令:段名 segment ;定义⼀个段,该段从此开始:段名 ends ;该段从此结束end:汇编程序结束的标记assume:含义为“假设”,假设某⼀段寄存器和程序中的某⼀个⽤segment…ends定义的段相关联,⽤于说明关联的关系。