搜档网
当前位置:搜档网 › 汇编语言学习笔记

汇编语言学习笔记

汇编语言学习笔记
汇编语言学习笔记

汇编语言学习笔记

---傻瓜学汇编

前言

当我在学汇编的时候发现一到了实际编程就发现学过的那些指令串不起来,什么浮点数啊整数啊,怎么跳转啊,怎么循环啊,脑袋立马变成浆糊。下面的文档是我的学习经历,希望对初学者在学习加密解密,软件调试,单片机编程有点帮助。

目录

1.编程环境的搭建

2.深入理解汇编语言的数据

3.顺序程序设计

4.分支结构程序设计

5.循环

6.数组及指针

7.函数

8.结构

9.综合运用

10.参考文献

一:编程环境的搭建

首先装好masm32v10 和windbg,和editplus,然后在editplus中输入下面的程序,具体的请参考罗云彬的那本书,里面有详尽的说明,编译运行看看:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

.data

msg db "hello,this is the first test program!", 0dh ,0ah,0

.code

start:

call main

ret

main proc

push offset msg

call printf

add esp,4

push offset msg

call printf

add esp,4

ret

mainendp

end start

下面是运行结果:

这里输出两行消息主要是我在写这个最简单的程序的时候发现他不换行,于是我在数据定义后面我加了“0ah,0dh”,呵呵,就是回车换行的十六进制表示,你也可以用其他方法试试,程序就不多解释了,后面会有更多的解释,不过你一定要走到这以步,才能进行下一章。

2.深入理解汇编语言的数据

整数常量及变量,先看一段很简单的汇编程序:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

.data

PRICE EQU 30

msg1 db "total=%d",0dh,0ah,0

.code

start:

call main

ret

main proc

local num:dword

local total:dword

mov num,10

mov eax,num

imul eax,eax,PRICE

mov total,eax

push offset msg1

call printf

add esp,4

ret

main endp

end start

程序的意思很简单就是在屏幕上打印出某个东西的价格,如过要你拿笔和纸算,拿你肯定很快就能算出来,但你让电脑怎么算呢?当电脑执行到第一个语句的时候,也就是num=10,它就把10放到某个地方并且记住这个值,寄存器或者内存,呵呵,它也就这两个地方,为什么要这么做呢?因为后面要用它来计算啊,为了算出这个值,电脑好的办法就是放在它的内存里,为什么不是寄存器?因为寄存器太少了,就那么几个,呵呵,所以了它就把10存在一个叫num的内存里,注意了哦,num是程序里的变量名,是存中里的一个位置的名称,它的值是10,你可能会问,不起名不行么?行,等下在调试器中你看到的就是没名的。来看看它在调试器中的样子:

num变成了[ebp-4]了,现在你想象有个几千行的程序如果都用[ebp-4]这样的名字的话,那我们会疯的,所以汇编程序就让我们给程序里面的变量起个直观的名字,而不是用具体的数字去让你去记住变量内存的位置。程序中imul eax,eax,1eh中的1eh就是个整形常量,也就是30.现在你应该对常量和变量有点感觉了吧。

再看个例子:

.386

.model flat,stdcall

option casemap:none

includelib msvcrt.lib

printf proto C :V ARARG

.data

a d

b 12h

b dw 1234h

c1 dd 12345678h

msg1 db "the number is=%xh",0dh,0ah,0

.code

start:

call main

ret

main proc

mov al,a

cbw

cwde

push eax

push offset msg1

call printf

add esp,8

mov ax,word ptr a

cwde

push eax

push offset msg1

call printf

add esp,8

mov eax,dword ptr a

push eax

push offset msg1

call printf

add sp,8

ret

main endp

end start

首先,你得想a,b,c1三个变量在程序中到底是怎么存的,是12 12 34 12 34 56 78,还是78 56 34 12 34 12 12呢?呵呵,用调试器载入程序看看就知道了:

哈哈,看到了没,正确的是这个:00403000:12 34 12 78 56 34 12 74-68,这是为什么?

还有就是这个程序打印的三个结果又是什么呢?是12h和0012h和00000012h吗?如果是,

那你就错了哦,应该是:the number is=12h the number is=3412h the number is=78123412h

呵呵,首先,你得明白这三个你定义的数据在内存是怎么存的,一个原则就是你定义的数据的高位存在内存中的高字节地址,你定义的第二个数据:1234h,高位字节是12吧,低位字节是34吧,所以编译器它先存34字节存在内存的低地址,然后再把12存在高地址,当然如果是你只定义了一个字节那顺序就没反了,就像你定义的第一个字节数据12好一样,同样第三个双自数据12345678h,编译器它就先存78好字节了,然后是56好字节,34h字节,12h字节。下面我们来看看程序:

mov al,a,就是是把12h放到al中,movzx ax,al 0扩展指令,将al中的字节扩展到ax中,不足的位用0填充,不改变al的值,al里面是什么值,扩展后ax的值还是等于al 中的值。movzx eax,ax ;0扩展指令,将ax中的字节扩展到eax中,不足的位用0填充,不改变ax的值,al里面是什么值,扩展后eax的值还是等于ax中的值。然后push eax,和push offset msg1,call printf 就是调用c语言库函数printf打印消息,就相当于c语言里面的:printf("the number is=%xh\n",a);下面的和这段一样,我就不写废话了。如果面对的是有符号数,那就得用movsx了,当然还有其他指令,后面再介绍。

浮点数:

在计算机内部,浮点数是以二进制表示的,所以,要先转换为二进制浮点数,转换分两部,整数部分的装换,采用“除2取余法”,小数部分的装换,采用“乘2取整法”,例如19.2,先将19 转换成二进制:10011,然后将0.2转换成二进制:00110011……0011,它是个无穷循环小数,然后就是规格化,分三种情况:如果定义的数据类型是dword或者是real4,那么符号位占一位,阶码占8位,位数占23位,总共是32位,如果定义的类型是qword或

real8,那么符号位占一位,阶码占11位,位数占52位,总共64位,如果定义的类型是real10或者是tword,那么阶码占15位,位数占64位,符号位占一位,总共80位。怎么算阶码呢?如果是32位,就将阶码加上127,然后转换成二进制,如果是64位,就加上1023,如果是80位,就加上16383。我们看看怎么将19.2转换成32位的二进制浮点数:

首先将19转换成二进制:10011,然后将0.2转换成二进制:00110011……0011,整理成32位就是:10011,001100110011001100110011001。然后规格化为:1,0011001100110011001100110011001x2的4次方,阶码为127加4等于131:10000011。所以当浮点数19.2表示为三种不同的数据类型为:

32位(dword,real4):0,10000011,0011001100110011001101

64位(qword,real8):0,100000000011,0011001100110011001100110011001100110011001100110011

80位:0,100000000000011,001100110011001100110011001100110011001100110011001100110011001100110011。

转换成16进制就是4199999Ah,40333333 33333333 h,403999999999999999ah。

然后我们yong程序来验证一下对不对。例子如下:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

.data

f1 real419.2

f2 real819.2

f3 real10 19.2

msg1 db "the floating number is=%g",0dh,0ah,0

.code

start:

call main

ret

main proc

local f:real8

fld dword ptr f1

fstp f

push dword ptr f+4

push dword ptr f+8

push offset msg1

call printf

add esp,12

push dword ptr f2+4

push dword ptr f2

push dword ptr offset msg1

call printf

add esp,12

fld f3

fstp qword ptr f

push dword ptr f+4

push dword ptr f+8

push offset msg1

call printf

add esp,12

ret

mainendp

end start

程序很简单,就是分别在屏幕上打印三个浮点值,如下图:

在这里我要说明下,我只有把32位和80位的转换为64位的,才能打印成功,这可能是库函数printf的原因,怎么转换呢?

32位浮点转换64位浮点:首先得借助一个64位的浮点局部变量:

local f:real8

fld dword ptr f1

fstp f

第一句定义了f位一个64位的浮点局部变量,第二句就是把32位浮点数转换为80位的,然后第三句就是把80位的转换位64位的。

80位浮点转换位64位浮点数:同样借助一个64位的浮点局部变量:

fld f3

fstp qword ptr f

第二句就是把80位的浮点转换位60位的。

但是这两句怎么解释呢:push dword ptr f2+4

push dword ptr f2

为什么要先把f2的高4位字节入栈呢?

好,我们先来看看这个数转换成64位的16进制为:40333333 33333333h,前面我说了高低对应原则,那么这个64位的16进制在内存中高4字节地址应该存40333333h,也就是存它的高4字节,然后是33333333h,但是,呵呵,在堆栈中的地址是从高往低增长的,所以我们应该先把这个数的高四字节入栈,也就是40333333h,怎么在内存中得到这高4字节呢?就是从f2+4处压入4字节就可以了,然后就是低4字节入栈。如果还没理解,用cdb调试一下就清楚了。

浮点与整数之间的转换:

先看例子成ch2-4:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

.data

f1 real819.2

f2 dword 20

msg1 db "the floating to int number is=%d",0dh,0ah,0

msg2 db "the int to floating number is=%f",0dh,0ah,0

.code

start:

call main

ret

main proc

local f:real8

fld f1

fistp dword ptr f

push dword ptr f

push offset msg1

call printf

add esp,8

fild f2

fstp f

push dword ptr f+4

push dword ptr f+8

push offset msg2

call printf

add esp,12

ret

mainendp

end start

运行结果为:

浮点数转换成整数:

fld f1

fistp word ptr f

首先我们还是借助了一个64位的局部变量,先把浮点数装入浮点寄存器,然后用装换整行的指令变成整数再存入一个局部变量就行了。

整数转换成浮点数:

fild f2

fstp f

先把整数用装换指令装入浮点寄存器,然后把浮点数存到一个局部变量就可以了。

我在后面会详细说名浮点数的运算和浮点寄存器的。

字符与字符串常量:

怎么定义他们?他们是以什么形式存在计算机中?

首先我们怎么在汇编中定义他们呢:先看看例子ch2-5:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

.data

str1 db 'this is a string test',0ah,0dh,0

str2 db "this is a string test",0ah,0dh,0

.code

start:

call main

ret

main proc

mov eax, offset str1

push offset str2

call printf

add esp,4

push offset str1

call printf

add esp,4

ret

mainendp

end start

程序就是在屏幕上打印两行消息,下面是运行结果:

然后我们用cdb调试器看看定义的那两个字符串变量在内存中到底是怎么样的:

恩,它们是以asii码的形式存在的。

其他的数据类型我会在下面的各个章节会随着编程的算法和调试一起讲解。

3:顺序程序设计

汇编语言的顺序编程比较好理解,就是在编程的时候没有跳转,没有循环,看看例子ch3-1:例ch3-1:输入三角形的边长,求三角形的面积。

我假设输入的三边长都是能构成三角形的,求三角形面积的公式为area= s(s-a)(s-b(s-c)。s=(a+b+c)/2.

这里要用到浮点指令,那就先回顾下浮点指令的用法:这里要加减乘除和平方根五种指令,由于Intel的浮点数据寄存器是种堆栈结构,我们要记住这一点。

先看看数据传送指令:fld和fild,fst,fstp:

fld 源操作数,源操作数可以是浮点寄存器和内存,这个指令主要是把源操作数压入浮点寄存器堆栈(其实就是st0),如果源操作数是整数,那就用fild。

Fst和fstp是把st(0)浮点寄存器中的数弹出到目的操作数中,目的操作数可以为浮点寄存器和内存。

加减法指令:fadd,faddp,fub,fsubp

第一种形式:fadd 目的操作数,源操作数。其中目的操作数,源操作数可以为浮点寄存器和内存。

第二种形式:fadd 源操作数,我本人比较喜欢这种,它不会把我脑海里的浮点寄存器的顺序弄乱,这种形式的源操作数只能是内存。减法指令同加法指令,就不多说了。

乘除法指令:fmul,fdiv

浮点的乘除法是不区分有符号和无符号数的,他们也有两种形式:

fmul目的操作数,源操作数和fmul 源操作数这两种形式,第一种操作数和源操作数可以为浮点寄存器和内存,但第二种源操作数值能为内存。

平方根指令:fsqrt

这个指令就一种形式就是fsqrt,就是把第0个浮点寄存器st0 的值变成平方根值然后存在st0中。

再回到例题中,我们应该先算s值,然后再算平方根下面的值然后求平方根就行了。

S值是三边长除以2,转换成浮点指令就是:fld a ;先把a值放到浮点寄存器st0中

再就是fadd b ;这个就是a+b,结果存在st0中

然后fadd c ;同上,结果存在st0中

现在算出了三边长的和,在除以2就ok了fiv two;结果在st0中,

最后把st0里面的值用fstp s 存到s中就把s值算出来了。

再来算根号下面的值,这里有乘法和减法,我们先算减法:fld s

fsub,a;这个就是s-a,结果在st0里

再fld s

fsub b;这个结果还是在st0里,但是上面那个s-a已经被推到st(1)这个浮点堆栈了啊,记住了。

再fld s

fsub c;这个结果还是在st0里,那么s-a被推到st(2)了,s-b被推到st(1)了,s-c的值在st(0)中,这里千万不能及乱了啊,下一步算乘法,先算s*(s-c),mul s;果在st0li

fmul st(0),st(1)这一步是算s*(s-a)*(s-b)

最后算s*(s-a)*(s-b)*(s-a)fmul st(0),st(2),然后把s*(s-a)*(s-b)*(s-a)的结果再求平方根fsqrt

再把这个平方根的值弹出到area中。

这是按照上面的想法写出的程序:

.386

.model flat,stdcall

option casemap:none

includelibmsvcrt.lib

printf proto C :V ARARG

scanf proto C :V ARARG

.data

msg1 db "%f,%f,%f",0

msg2 db "area=%7.2f",0ah,0dh,0

msg3 db "please input three floating numbers",0ah,0dh,0

two real42.0

.code

start:

call main

ret

main proc

local a:real4

local b:real4

local c1:real4

local s:real4

local a rea:real8

push offset msg3

call printf

add esp,4

lea eax,c1

push eax

lea eax,b

push eax

lea eax,a

push eax

push offset msg1

call scanf

add esp,16

fld a

fadd b

fadd c1

fdiv two

fstp s

fsub a

fsub b

fsub c1

fmul s

fmul st,st(1)

fmul st,st(2)

fsqrt

fstp area

push dword ptr area+8

push dword ptr area+4

push offset msg2

call printf

add esp,12

ret

mainendp

end start

编译运行:下面是结果:

但是出乎意料哦,错了,怎么办呢?你发现什么问题了没?那只有调试看看了,用cdb -2 C:\w\b\ch3\ch3-1\ch3-1打开程序然后逐步调试看看,当跟踪到下面这句是就发现有问题了:

就是fstp,s,也就是00401041 d95df0 fstp dword ptr [ebp-10h] ss:0023:0013ffac=a9e45d08,然后发现st中的值被弹走了,但紧接着又用st(0)用与下一步

进行计算了,先推出调试,改动下再运行看看对不对,但结果还是错的:

那还得继续调试了,发现我对fsub指令理解错了,原来这个指令执行完之后它不把结果推到下一个浮点堆栈:

汇编语言 快速入门

“哎哟,哥们儿,还捣鼓汇编呢?那东西没用,兄弟用VB"钓"一个API就够你忙活个十天半月的,还不一定搞出来。”此君之言倒也不虚,那吾等还有无必要研他一究呢?(废话,当然有啦!要不然你写这篇文章干嘛。)别急,别急,让我把这个中原委慢慢道来:一、所有电脑语言写出的程序运行时在内存中都以机器码方式存储,机器码可以被比较准确的翻译成汇编语言,这是因为汇编语言兼容性最好,故几乎所有跟踪、调试工具(包括WIN95/98下)都是以汇编示人的,如果阁下对CRACK颇感兴趣……;二、汇编直接与硬件打交道,如果你想搞通程序在执行时在电脑中的来龙去脉,也就是搞清电脑每个组成部分究竟在干什么、究竟怎么干?一个真正的硬件发烧友,不懂这些可不行。三、如今玩DOS的多是“高手”,如能像吾一样混入(我不是高手)“高手”内部,不仅可以从“高手”朋友那儿套些黑客级“机密”,还可以自诩“高手”尽情享受强烈的虚荣感--#$%&“醒醒!” 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指

8086 汇编例程

汇编语言(应用)程序(80X86/Pentium) 设计:乐金松 广东工业大学电子与信息工程学院

;This program for:R0R1-R2R3=R4R5 ;---------------------------------------------------------------- ;define stack segment STACK SEGMENT STACK 'STACK' DB 1024 DUP (0) STACK ENDS ;define data segment DATA SEGMENT R0 DW (?) R1 DW (?) R2 DW (?) R3 DW (?) R4 DW (?) R5 DW (?) R6 DW (?) R7 DW (?) DATA ENDS ;define code segment NDWSUB SEGMENT ; MAIN PROC FAR ASSUME CS:NDWSUB,DS:DATA,SS:STACK ; START: PUSH DS ;return DOS standard program MOV AX,0 PUSH AX MOV AX,DATA ;set DS MOV DS,AX MOV AX,R1 SUB AX,R3 MOV R5,AX MOV AX,R0 SBB AX,R2 MOV R4,AX RET MAIN ENDP NDWSUB ENDS END START

;This program for:R0R1+R2R3=R4R5 ;---------------------------------------------------------------- ;define stack segment STACK SEGMENT STACK 'STACK' DB 1024 DUP (0) STACK ENDS ;define data segment DATA SEGMENT R0 DW (?) R1 DW (?) R2 DW (?) R3 DW (?) R4 DW (?) R5 DW (?) R6 DW (?) R7 DW (?) DATA ENDS ;define code segment NDWADD SEGMENT ; MAIN PROC FAR ASSUME CS:NDWADD,DS:DATA,SS:STACK ; START: PUSH DS ;return DOS standard program MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV AX,R1 ADD AX,R3 MOV R5,AX MOV AX,R0 ADC AX,R2 MOV R4,AX RET MAIN ENDP ;end process NDWADD ENDS ;end segment END START

汇编语言知识大全

第一章基础知识: 一.机器码:1.计算机只认识0,1两种状态。而机器码只能由0,1组成。故机器码相当难认,故产生了汇编语言。 2.其中汇编由三类指令形成:汇编指令(有机器码对应),伪指令,其他符号(编译的时候有用)。 每一总CPU都有自己的指令集;注意学习的侧重点。 二.存储器:1.存储单元中数据和指令没任何差别。 2.存储单元:Eg:128个储存单元(0~127)128byte。 线: 1.地址总线:寻址用,参数(宽度)为N根,则可以寻到2^N个内存单元。 据总线:传送数据用,参数为N根,一次可以传送N/8个存储单元。 3.控制总线:cpu对元器件的控制能力。越多控制力越强。 四.内存地址空间:1.由地址总线决定大小。 2.主板:cpu和核心器件(或接口卡)用地址总线,数据总线,控制总 线连接起来。 3.接口卡:由于cpu不能直接控制外设,需通过接口卡间接控制。

4.各类存储器芯片:RAM,BIOS(主板,各芯片)的ROM,接卡槽的 RAM CPU在操控他们的时候,把他们都当作内存来对待,把他们总的看作一个由 若干个存储单元组成的逻辑存储器,即我们所说的内存地址空间。 自己的一点理解:CPU对内存的操作是一样的,但是在cpu,内存,芯片之间的硬件本身所牵扯的线是不同的。所以一些地址的功能是对应一些芯片的。 第二章寄存器 引入:CPU中含有运算器,寄存器,控制器(由内部总线连接)。而寄存器是可以用来指令读写的部件。8086有14个寄存器(都是16位,2个存储空间)。 一.通用寄存器(ax,bx,cx,dx),16位,可以分为高低位 注意1.范围:16位的2^16-1,8位的2^8-1 2.进行数据传送或运算时要注意位数对应,否则会报错 二.字:1. 1个字==2个字节。 2. 在寄存器中的存储:0x高位字节低位字节;单元认定的是低单元 数制,16进制h,2进制b

汇编语言程序设计实验报告

微机原理实验报告 实验名称汇编语言程序设计 一、实验目的 1、掌握Lab6000p实验教学系统基本操作; 2、掌握8088/8086汇编语言的基本语法结构; 3、熟悉8088/8086汇编语言程序设计基本方法 二、实验设备 装有emu8086软件的PC机 三、实验内容 1、有一个10字节的数组,其值分别是80H,03H,5AH,FFH, 97H,64H,BBH,7FH,0FH,D8H。编程并显示结果:如果数组是无符号数,求出最大值,并显示; 如果数组是有符号数,求出最大值,并显示。 2、将二进制数500H转换成二-十进制(BCD)码,并显示“500H 的BCD是:” 3、将二-十进制码(BCD)7693转换成ASCII码,并显示“BCD 码7693的ASCII是:” 4、两个长度均为100的内存块,先将内存块1全部写上88H,再 将内存块1的内容移至内存块2。在移动的过程中,显示移动次数1,2 ,3…0AH…64H(16进制-ASCII码并显示子程序) 5、键盘输入一个小写字母(a~z),转换成大写字母 显示:请输入一个小写字母(a~z): 转换后的大写字母是: 6、实现4字节无符号数加法程序,并显示结果,如99223344H + 第1页

99223344H = xxxxxxxxH 四、实验代码及结果 实验代码见代码附录 1.1程序运行结果 图1 无符号最大值结果截图 1.1 程序运行结果

图2 有符号最大值截图2.0 程序运行结果

图3 BCD码显示3.0 程序运行结果

图4 ASCII码显示4.0 程序运行结果

图5 移动次数显示5.0 程序运行结果

汇编语言入门

汇编语言入门教程 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O 控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086 有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP(Base Pointer):基址指针寄存器,可用作SS 的一个相对基址位置;SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针;DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR(Flag Register),有九个有意义的标志,将在下文用到时详细说明。 内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放

汇编语言基本关键字

汇编语言基本关键字 aaa对非压缩BCD码加法之和调整 aas 对非压缩BCD码减法之差调整 aam乘法调整aad被除数调整 add不带进位标志位的加法adc带进位标志位的加法 and逻辑与 assume指定段寄存器 bswap双字单操作数内部交换 bt位测试bts位测试并置一 btr位测试并清零btc位测试并取反 bsf/bsr正,反向位扫描 call调用 cbw字节转换为字cwd字转换为双字cwde字转换为扩展的双字cdq双字转换为四字 cmp比较cmpxchg比较并交换 cmps串比较 code定义简化代码段 const定义简化常数数据段 daa对压缩BCD码加法之和调整das对压缩BCD码减法之差调整 data定义简化数据段 db/dw/dd/dq/dt定义字节/字/双字/四字/十字变量 dec减一

df定义32位便宜地址的远地址指针 div无符号数除法 equ等价textequ文本等价 even取偶偏移地址 fardata,fardata定义简化独立数据段 group定义段组 idiv有符号整数除法 imul有符号整数乘法 in输入 inc加一 ins/outs输入/输出串元素 jcxz/jecxz若cx=0/ecx=0,跳转 jmpdopd无条件跳转到DOPD 处取出指令继续执行 label为$定义符号 Lahf 标志位低八位送AH lea 偏移地址送通用寄存器lda传送进入数据段的地址指针 les传送进入附加数据段的地址指针lfs传送进入FS段的地址指针lgs传送进入GS段的地址指针lss传送进入堆栈段的地址指针 local说明局部变量 lods读出串元素 Loop/loopd无条件循环cx/ecx为循环次数 loopnz/loopnzd非零或不等时循环,cx/ecx为循环次数

《汇编语言程序设计》课程教学改革与实践

144747 学科教育论文 《汇编语言程序设计》课程教学改革与 实践 1课程的现状 汇编语言不同于其它高级语言,必须要求编程人员有一定的硬件基础,如对CPU的结构、CPU与存储器等部件的数据传送过程必须要有基本的了解,这样才能学好这门课程。在教学过程中,我们发现学生对高级语言编程学习积极性高,对汇编语言课程缺乏兴趣,因为课程本身指令复杂,规定繁多,再加上学习汇编指令前对CPU的相关工作过程理解不透,导致学生厌学,又由于本课程面对的低年级学生只有高级语言的基础,习惯于高级语言的自然表达,初次接触计算机硬件知识心理上有恐惧感,更难以适应繁杂的低级语言。 针对本课程的特点,对教学内容、环节、过程等进行了精心设计,下面就教学方法的设计、实践教学方法、课程考核形式等方面进行的一系列改革进行详细探讨。 2教学方法设计改革

为了避免学生因指令复杂,规定繁多、难度大而对该课程产生畏惧的学习心理,教师有必要对教学内容进行合理组织,对教学过程进行精心的设计。 2.1利用FLASH技术,使教学难点容易理解 在多年的教学过程中,我发现学生在学习CPU结构这章节中,对介绍的CPU由哪些寄存器(名称、大小)构成,各个寄存器的含义,用途,CPU与存储器等部件的数据传送过程,会觉得很抽象,多数同学都是采用死记硬背的方式,这章节是第二章节的内容,也是能否学好该课程关键的一章,如果理解不深,这无疑为后续的学习,特别是寻址方式的学习埋下了隐患。 针对这个问题,教师有必要对教学过程进行精心的设计。 在这章节中我们利用FLASH技术,把各种寻址方式下传送指令的CPU与存储器等部件的数据传送过程以动画形式展现给学生,使得复杂,抽象的过程变得直观,学生理解比较容易,也加深了对寻址方式的记忆。 2.2对比法教学

Windows X86-64位汇编语言入门

Windows X86-64位汇编语言入门 Windows X64汇编入门(1) 最近断断续续接触了些64位汇编的知识,这里小结一下,一是阶段学习的回顾,二是希望对64位汇编新手有所帮助。我也是刚接触这方面知识,文中肯定有错误之处,大家多指正。 文章的标题包含了本文的四方面主要内容: (1)Windows:本文是在windows环境下的汇编程序设计,调试环境为Windows Vista 64位版,调用的均为windows API。 (2)X64:本文讨论的是x64汇编,这里的x64表示AMD64和Intel的EM64T,而不包括IA64。至于三者间的区别,可自行搜索。 (3)汇编:顾名思义,本文讨论的编程语言是汇编,其它高级语言的64位编程均不属于讨论范畴。 (4)入门:既是入门,便不会很全。其一,文中有很多知识仅仅点到为止,更深入的学习留待日后努力。其二,便于类似我这样刚接触x64汇编的新手入门。 本文所有代码的调试环境:Windows Vista x64,Intel Core 2 Duo。 1. 建立开发环境 1.1 编译器的选择 对应于不同的x64汇编工具,开发环境也有所不同。最普遍的要算微软的MASM,在x64环境中,相应的编译器已经更名为ml64.exe,随Visual Studio 2005一起发布。因此,如果你是微软的忠实fans,直接安装VS2005既可。运行时,只需打开相应的64位命令行窗口(图1),便可以用ml64进行编译了。

第二个推荐的编译器是GoASM,共包含三个文件:GoASM编译器、GoLINK链接器和GoRC 资源编译器,且自带了Include目录。它的最大好外是小,不用为了学习64位汇编安装几个G 的VS。因此,本文的代码就在GoASM下编译。 第三个Yasm,因为不熟,所以不再赘述,感兴趣的朋友自行测试吧。 不同的编译器,语法会有一定差别,这在下面再说。 1.2 IDE的选择 搜遍了Internet也没有找到支持asm64的IDE,甚至连个Editor都没有。因此,最简单的方法是自行修改EditPlus的masm语法文件,这也是我采用的方法,至少可以得到语法高亮。当然,如果你懒得动手,那就用notepad吧。 没有IDE,每次编译时都要手动输入不少参数和选项,做个批处理就行了。 1.3 硬件与操作系统 硬件要求就是64位的CPU。操作系统也必须是64位的,如果在64位的CPU上安装了

汇编语言基础知识

汇编语言基础知识 汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件系统的结构,才能有 效地应用汇编语言对其编程,因此,本章对硬件系统结构的问题进行部分探讨,首先介绍了计算机的基本结构、Intel 公司微处理器的发展、计算机的语言以及汇编语言的特点,在此基础上重点介绍寄存器、内存组织等汇编语言所涉及到的基本知识。 1.1 微型计算机概述 微型计算机由中央处理器(Central Processing Unit ,CPU )、存储器、输入输出接口电路和总线构成。CPU 如同微型计算机的心脏,它的性能决定了整个微型计算机的各项关键指标。存储器包括随机存储器(Random Access Memory ,RAM )和只读存储器(Read Only Memory ,ROM )。输入输出接口电路用来连接外部设备和微型计算机。总线为CPU 和其他部件之间提供数据、地址和控制信息的传输通道。如图1.1所示为微型计算机的基本结构。 外部设备存储器输入输出接口电路中央处理器 CPU 地址总线 数据总线 控制总线 图1.1 微型计算机基本结构 特别要提到的是微型计算机的总线结构,它使系统中各功能部件之间的相互关系变 为各个部件面向总线的单一关系。一个部件只要符合总线结构标准, 就可以连接到采用这种总线结构的系统中,使系统功能得到扩展。 数据总线用来在CPU 与内存或其他部件之间进行数据传送。它是双向的,数据总线 的位宽决定了CPU 和外界的数据传送速度,8位数据总线一次可传送一个8位二进制数据(即一个字节),16位数据总线一次可传送两个字节。在微型计算机中,数据的含义是广义的,数据总线上传送的不一定是真正的数据,而可能是指令代码、状态量或控制量。 地址总线专门用来传送地址信息,它是单向的,地址总线的位数决定了 CPU 可以直接寻址的内存范围。如 CPU 的地址总线的宽度为N ,则CPU 最多可以寻找2N 个内存单 元。

常用汇编语言8086程序集锦

一、计算X+Y=Z,将结果Z存入某存储单元。 (1). 实验程序如下: STACK SEGMENT STACK DW 64 DUP(?) STACK ENDS DATA SEGMENT XL DW ? ;请在此处给X低位赋值 XH DW ? ;请在此处给X高位赋值 YL DW ? ;请在此处给Y低位赋值 YH DW ? ;请在此处给Y高位赋值 ZL DW ? ZH DW ? DATA E NDS CODE S EGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AX,XL ;X低位送AX ADD AX,YL ;X低位加Y低位 MOV ZL,AX ;存低位和 MOV AX,XH ;X高位送AX ADC AX,YH ;X高位加Y高位 MOV ZH,AX A1: JMP A1 CODE E NDS END START 二、计算X-Y=Z,其中X、Y、Z为BCD码。实验程序及流程如下:STACK SEGMENT STACK DW 64 DUP(?) STACK ENDS DATA SEGMENT X DW ? ;请在此处给X赋值 Y DW ? ;请在此处给Y赋值 Z DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AH,00H SAHF MOV CX,0002H LEA SI, X LEA DI, Z A1: MOV AL,[SI] SBB AL,[SI+02H] DAS PUSHF AND AL,0FH

8086汇编语言小结

8086/8088汇编指令小结 一、数据传送指令; 二、算术指令; 三、逻辑指令; 四、串处理指令; 五、控制转移指令; 六、处理机控制指令。 (详情见全文) 一、数据传送指令 1.通用数据传送指令 MOV(Move)传送 PUSH(Push onto the stack)进栈 POP(Pop from the stack)出栈 XCHG(Exchange)交换 .MOV指令 格式为: MOV DST,SRC 执行的操作:(DST)<-(SRC) .PUSH进栈指令 格式为:PUSH SRC 执行的操作:(SP)<-(SP)-2 ((SP)+1,(SP))<-(SRC) .POP出栈指令 格式为:POP DST 执行的操作:(DST)<-((SP+1),(SP)) (SP)<-(SP)+2 .XCHG 交换指令 格式为:XCHG OPR1,OPR2 执行的操作:(OPR1)<-->(OPR2) 2.累加器专用传送指令 IN(Input) 输入 OUT(Output) 输出 XLAT(Translate) 换码 这组指令只限于使用累加器AX或AL传送信息. .IN 输入指令 长格式为: IN AL,PORT(字节) IN AX,PORT(字) 执行的操作: (AL)<-(PORT)(字节)

(AX)<-(PORT+1,PORT)(字) 短格式为: IN AL,DX(字节) IN AX,DX(字) 执行的操作: AL<-((DX))(字节) AX<-((DX)+1,DX)(字) .OUT 输出指令 长格式为: OUT PORT,AL(字节) OUT PORT,AX(字) 执行的操作: (PORT)<-(AL)(字节) (PORT+1,PORT)<-(AX)(字) 短格式为: OUT DX,AL(字节) OUT DX,AX(字) 执行的操作: ((DX))<-(AL)(字节) ((DX)+1,(DX))<-AX(字) 在IBM-PC机里,外部设备最多可有65536个I/O端口,端口(即外设的端口地址)为0000~FFFFH.其中前256个端口(0~FFH)可以直接在指令中指定,这就是长格式中的PORT,此时机器指令用二个字节表示,第二个字节就是端口号.所以用长格式时可以在指定中直接指定端口号,但只限于前256个端口.当端口 号>=256时,只能使用短格式,此时,必须先把端口号放到DX寄存器中(端口号可以从0000到0FFFFH),然后再用IN或OUT指令来传送信息. .XLAT 换码指令 格式为: XLAT OPR 或: XLAT 执行的操作:(AL)<-((BX)+(AL)) 3.有效地址送寄存器指令 LEA(Load effective address)有效地址送寄存器 LDS(Load DS with Pointer)指针送寄存器和DS LES(Load ES with Pointer)指针送寄存器和ES .LEA 有效地址送寄存器 格式为: LEA REG,SRC 执行的操作:(REG)<-SRC 指令把源操作数的有效地址送到指定的寄存器中. .LDS 指针送寄存器和DS指令 格式为: LDS REG,SRC 执行的操作:(REG)<-(SRC) (DS)<-(SRC+2) 把源操作数指定的4个相继字节送到由指令指定的寄存器及DS寄存器中.该指令常指定SI寄存器. .LES 指针送寄存器和ES指令 格式为: LES REG,SRC 执行的操作: (REG)<-(SRC) (ES)<-(SRC+2) 把源操作数指定的4个相继字节送到由指令指定的寄存器及ES寄存器中.该

8086汇编语言习题解答

8086/8088汇编语言习题解答 第一章 、试根据自己使用计算机的经历,列举几个必须使用或最好是使用汇编语言编制程序的事例。 、试完成下列数制间的转换 ⑴、十进制数转换为8位二进制数 十进制:100 对应二进制:01100100B 十进制:56 对应二进制:00111000B 十进制:111 对应二进制:01101111B 十进制: 120 对应二进制:01111000B 十进制: 70 对应二进制:01000110B ⑵、8位二进制数(无符号数)转换为十进制数 二进制:01010101B 对应十进制:85 二进制:B 对应十进制:170 二进制:B 对应十进制:240 二进制:00001111B 对应十进制:15 ⑶、十进制数转换为十六进制数 十进制:40 对应二进制:00101000B 十进制:80 对应二进制:01010000B 十进制:105 对应二进制:01101001B 十进制: 114 对应二进制:01101101B 十进制: 207 对应二进制:B

、试把下面用补码表示的二进制数转换为对应的十进制真值 二进制补码:01111000 对应的十进制值数真值:+120 二进制补码:对应的十进制值数真值:-39 二进制补码:对应的十进制值数真值:-127 二进制补码:对应的十进制值数真值:-120 二进制补码:00100111 对应的十进制值数真值:+39 二进制补码:对应的十进制值数真值:-16 、由键盘输入字符通常都是以该字符的ASCII码形式表示的。若现在从键盘上输入十六进制数0~F,那么应如何处理才能把十六进制转换为4位二进制数0000~1111. 答:将键盘输入的数0~F的ASCII码,每输入一个字符,减去30H后,再存入内存,这样就完成了把从键盘上输入的十六进制ASCII码转换为4位二进制数0000~1111. 、试分别判断下列各组数据中哪个数据最大哪个最小 ①、A= B=0,101D C=0,101H ②、A=1011B B=1011D C=1011H 答:第①组:A=1×21-+1×23-= B= C=1×161-+163-=+= 所以A最大,C最小 第②组,B最大,A=B最小 、现有一个二进制数.若将该数看着是无符号数、原码表示的带符号数、补

汇编语言入门教程

汇编语言入门教程 2007-04-29 22:04对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩DEBUG,有时CRACK 出一个小软件比完成一个程序更有成就感(就像学电脑先玩游戏一样)。某些高深的指令事实上只对有经验的汇编程序员有用,对我们而言,太过高深了。为了使学习汇编语言有个好的开始,你必须要先排除那些华丽复杂的命令,将注意力集中在最重要的几个指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科书中完成上述目标,谈何容易,所以本人整理了这篇超浓缩(用WINZIP、WINRAR…依次压迫,嘿嘿!)教程。大言不惭的说,看通本文,你完全可以“不经意”间在前辈或是后生卖弄一下DEBUG,很有成就感的,试试看!那么――这个接下来呢?――Here we go!(阅读时看不懂不要紧,下文必有分解) 因为汇编是通过CPU和内存跟硬件对话的,所以我们不得不先了解一下CPU和内存:(关于数的进制问题在此不提) CPU是可以执行电脑所有算术╱逻辑运算与基本I/O 控制功能的一块芯片。一种汇编语言只能用于特定的CPU。也就是说,不同的CPU其汇编语言的指令语法亦不相同。个人电脑由1981年推出至今,其CPU发展过程为:8086→80286→80386→80486→PENTIUM →……,还有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不过多了些指令(如多能奔腾的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。为确保汇编程序可以适用于各种机型,所以推荐使用8086汇编语言,其兼容性最佳。本文所提均为8086汇编语言。寄存器(Register)是CPU内部的元件,所以在寄存器之间的数据传送非常快。用途:1.可将寄存器内的数据执行算术及逻辑运算。2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。3.可以用来读写数据到电脑的周边设备。8086 有8个8位数据寄存器,这些8位寄存器可分别组成16位寄存器:AH&AL=AX:累加寄存器,常用于运算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:计数寄存器,常用于计数;DH&DL=DX:数据寄存器,常用于数据传递。为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。除了前面所提的寄存器外,还有一些特殊功能的寄存器:IP(Intruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置;SI(Source Index):源变址寄存器可用来存放相对于DS 段之源变址指针;DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。还有一个标志寄存器FR(Flag Register),有九个有意义的标志,将在下文用到时详细说明。

8086汇编语言上机调试及基本操作

深 圳 大 学 实 验 报 告 课程名称: 微机原理实验 实验名称: 8086汇编语言上机调试及基本操作 学院: 物理科学与技术学院 组号: 指导教师: 李雄军 报告人:林成业 学号: 2012180073 实验地点: 科技楼302 实验时间:2014年9月24日 实验报告提交时间: 2014年10月15日 得分 教师签名 批改日期 课程编号 题目类型

一、实验目的: (1)掌握常用DEBUG命令: G,D,R,T,U,Q。 (2)掌握工具软件EMU8086。 (3)掌握完整程序设计方法的格式,能正确书写数据段,代码段等。 (4)掌握简单的数值转换算法 二、实验原理 1.实验说明: 计算机中的数值有各种表达方式,这是计算机的基础。掌握各种数制之间的转换是一种基本功。 2.程序框图:对于0-999(即000H-3E7H)范围内的二进制数 3.参考程序: ; 将AX中的三位数拆为三个BCD码, 并存入Result 开始的三个单元 DATA SEGMENT; 数据段 RESULT_1 DB 1 RESULT_2 DB 1 RESULT_3 DB 1 DATA ENDS STACK SEGMENT STACK ; 堆栈段 STA DB 64 DUP(0) STACK_TOP DB 0 STACK ENDS CODE SEGMENT; 代码段 ASSUME CS:CODE , DS:DATA , ES:DATA , SS:STACK

START: MOV AX, DATA MOV DS, AX ; 设置数据段 MOV AX, STACK MOV SS, AX ; 设置堆栈段 LEA SP, STACK_TOP ; 设置栈顶指针 MOV AX, 2afH MOV CL, 100 DIV CL MOV RESULT_1, AL ; 除以100, 得百位数 MOV AL, AH MOV AH, 0 MOV CL, 10 DIV CL MOV RESULT_2, AL ; 余数除以10, 得十位数 MOV RESULT_3, AH ; 余数为个位数 MOV AX,4C00H ; 返回DOS INT 21H ; CODE ENDS END START ; 最后一行要按回车键 三、实验及报告要求: 1)用合适的编辑软件编辑以上源文件并存入合适目录;要求补充注释未注释的 伪指令和指令; 2)分别在DOS和Windows下编译、连接生成可执行文件,比较两个环 境下生成的机器码的长度和内容;试指出第2、5、7、10、14条指令的IP和机器码。 3)分别在debug和emu8086下调试该可执行文件,给出程序运行时的各段 地址(CS=?,DS=?SS=?ES=?)举例说明debug的t,d,g,u等命令操作方法并对寄存器的变化作出解释;试改变被转换的三位数,并解释转换过程中标志寄存器中各标志位的结果;如何观察转换结果的变化?4)写出完整的实验报告,特别是“实验结果”与“实验总结体会”部分,是评分的 主要依据。 5)实验总结中要求结合实验中的经验、教训或体会对汇编语言格式、调试方法 和微机原理学习方法作出总结。 四、实验结果与分析 1.建立汇编源程序ASM文件。 DATA SEGMENT 数据段 RESULT_1 DB 1 结果1是低八位,初始量为’1’ RESULT_2 DB 1 结果1是低八位 RESULT_3 DB 1 结果1是低八位 DATA ENDS 结束数据段 STACK SEGMENT STACK 堆栈段 STA DB 64 DUP(0) 堆栈段初始化

汇编语言基础练习题目

一、填空 1.在8086/8088的计算机中,存储单元的20位物理地址由两部分组成,即16 位的段地址和16位的偏移地址,物理地址= 段地址×10H+偏移量。 2.段的起始地址必须是某小段的首地址,它能被 10H 整除。 3.已知01020H字单元的内容为6A58H,请分别写出它的两个字节单元的地址和内容:(01020H)=58H,(01021H)=6AH。 4.指令执行后,若标志寄存器的ZF=0,则表示结果不为0;若SF=0,则表示结果的符号是正号,即结果为正数。 5.控制器从存储器取出一条指令后,指令指针寄存器IP的内容是将要执行的下一条指令开始的偏移地址。 6.段地址和偏移地址为1000:127B的存储单元的物理地址是 1127BH。 解:由物理地址= 段地址×10H+偏移量的公式可得 物理地址=1000H×10H+127BH=10000H+127BH=1127BH。 二、选择 1.与CS寄存器组合才能形成代码段的物理地址的寄存器是( C )。 A.SP寄存器 B.BP寄存器 C.IP寄存器 D.BX寄存器 2.如果存储器分段时,一个段最多允许16K个字单元,那么表示该段内偏移地址的二进制数至少是( A )。 A.15位 B.16位 C.17位 D.18位 解:16K个字单元,即为32K个字节单元。由于2的15次方为32K,因此至少需要15位二进制数才能表示16K个字单元。 3.已知一数据段的段地址是0100H,这个段的第6个字单元的物理地址是( B )。 A.01010H B.0100AH C.01012H D.01006H 解:由于一个字单元占用两个字节,第一个字单元的偏移地址为0000H,因此第一个字单元的物理地址为01000H。以后每一个字单元的地址在前一个的基

《汇编语言》学习笔记(清华大学 王爽)

清华大学《汇编语言》(王爽)读书笔记 第一章基础知识 ◎汇编语言由3类指令组成 汇编指令:机器码的助记符,有对应机器码。 伪指令:没有对应机器码,由编译器执行,计算机并不执行 其他符号:如+-*/,由编译器识别,没有对应机器码 ◎一个CPU有n根地址线,则可以所这个CPU的地址线宽度为n,这样的CPU最多可以寻找2的n 次方个内存单元。 ◎ 1K=2^10B 1M=2^20B 1G=2^30B ◎8086 CPU地址总线宽度为20,寻址范围为00000~FFFFF 00000~9FFFF 主存储器地址空间(RAM) A0000~BFFFF 显存地址空间 C0000~FFFFF 各类ROM地址空间 第二章寄存器(CPU工作原理) ◎16位结构描述了一个CPU具有下面几个方面的结构特性 运算器一次最多可以处理16位的数据 寄存器的最大宽度为16位 寄存器和运算器之间的通路为16位 ◎8086有20位地址总线,可以传送20位地址,达到1M的寻址能力。采用在内部用两个16位地址合成的方法来形成一个20位的物理地址 ◎物理地址 = 段地址 × 16 + 偏移地址 ◎在编程是可以根据需要,将若干地址连续的内存单元看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。段地址×16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址位16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB ◎8086有四个段寄存器 CS、DS、SS、ES ◎CS为代码段寄存器,IP为指令指针寄存器。任意时刻,设CS中内容为M、IP中内容为N,8086CPU从内存M×16+N读取一条指令执行 ◎不能用mov修改CS、IP,因为8086CPU没有提供这样功能,可用指令JMP 段地址:偏移地址。JMP 2AE3:3 JMP AX 修改IP 第三章寄存器(内存访问) ◎DS数据段寄存器。不能将数据直接送入段寄存器,所以『MOV DS, 1』不正确 ◎字在存储时要两个连续的内存单元,低位在低地址,高位在高地址 ◎[address]表示一个偏移地址为address的内存单元 ◎SS:SP指向栈顶元素 ◎PUSH AX:(1)SP = SP - 2;(2)AX送入SS:SP ◎POP AX:(1)SS:SP送入AX;(2)SP = SP + 2 ◎PUSH/POP 寄存器 PUSH/POP 段寄存器 PUSH/POP 内存单元 第四章第1个程序 ◎可执行文件包含两部分:程序和数据,相关的描述信息 ◎程序加载后, ds中存放这程序所在内存区的段地址,这个内存区的偏移地址为0,策程序所在的内存区的地址为ds:0;这个内存区的前256个字节中存放的是PSP,dos用来和程序进行通信。从256字节处向后的空间存放的是程序。 第五章 [BX]和loop指令 ◎[BX]表示一个内存单元,它的段地址在ds中,偏移地址在bx中。MOV AX,[BX] MOV AL,[BX]

新版汇编语言程序设计钱晓捷第1章习题答案

第1章汇编语言基础知识(全) 2010-10-18 19:32:40| 分类:答案集锦| 标签:|字号大中小订阅 第1章汇编语言基础知识 〔习题1.1〕简述计算机系统的硬件组成及各部分作用。 〔解答〕 CPU:包括运算器、控制器和寄存器组。运算器执行所有的算术和逻辑运算;控制器负责把指指令逐条从存储器中取出,经译码分析后向机器发出各种控制命令,并正确完成程序所要求的功能;寄存器组为 处理单元提供所需要的数据。 存储器:是计算机的记忆部件,它用来存放程序以及程序中所涉及的数据。 外部设备:实现人机交换和机间的通信。 〔习题1.2〕明确下列概念或符号: 主存和辅存,RAM和ROM,存储器地址和I/O端口,KB、MB、GB和TB 〔解答〕 主存又称内存是主存储器的简称,主存储器存放当前正在执行的程序和使用的数据,CPU可以直接存取,它由半导体存储器芯片构成其成本高、容量小、但速度快。辅存是辅助存储器的简称,辅存可用来长期保存大量程序和数据,CPU需要通过I/O接口访问,它由磁盘或光盘构成,其成本低、容量大,但速 度慢。 RAM是随机存取存储器的英语简写,由于CPU可以从RAM读信息,也可以向RAM写入信息,所以RAM也被称为读写存储器,RAM型半导体存储器可以按地址随机读写,但这类存储器在断电后不能保存信息;而ROM中的信息只能被读出,不能被修改,ROM型半导体通常只能被读出,但这类存储器断电 后能保存信息。 存储器由大量存储单元组成。为了区别每个单元,我们将它们编号,于是,每个存储单元就有了一个存储地址,I/O接口是由一组寄存器组成,为了区别它们,各个寄存器进行了编号,形成I/O地址,通常 称做I/O端口。 KB是千字节、MB是兆字节、GB是吉字节和TB是太字节,它们都是表示存储器存储单元的单位。 〔习题1.3〕什么是汇编语言源程序、汇编程序、目标程序? 〔解答〕 用汇编语言书写的程序就称为汇编语言源程序;完成汇编工作的程序就是汇编程序;由汇编程序编 译通过的程序就是目标程序。

相关主题