搜档网
当前位置:搜档网 › 汇编语言入门

汇编语言入门

汇编语言入门
汇编语言入门

汇编语言入门知识

汇编语言入门知识 (1)

gcc中的内嵌汇编语言(INTEL i386 平台) (3)

一.声明 (3)

二.简介 (3)

三.A T&T的汇编语言语法格式 (3)

四.gcc 的内嵌汇编语言语句 asm (7)

8086/8088 指令详解 (7)

一、数据传送指令 (8)

1.通用数据传送指令 (8)

2.累加器专用传送指令 (8)

3.有效地址送寄存器指令 (10)

4.标志寄存器传送指令 (11)

二、算术指令 (11)

1.加法指令 (11)

2.减法指令 (12)

3.乘法指令 (13)

4.除法指令 (13)

三、逻辑指令 (15)

1.逻辑运算指令 (15)

2.移位指令 (16)

四、串处理指令 (16)

1.与 REP 相配合工作的 MOVS,STOS 和 LODS 指令 (16)

2.与 REPE/REPZ和 REPNZ/REPNE 联合工作的 CMPS 和 SCAS 指令 (18)

五、控制转移指令 (20)

1.无条件转移指令 (20)

2.条件转移指令 (21)

1)根据单个条件标志的设置情况转移 (21)

2)比较两个无符号数,并根据比较的结果转移 (22)

3)比较两个带符号数,并根据比较的结果转移 (23)

4)测试 CX的值为 0则转移指令 (23)

3.循环指令 (24)

4.子程序 (24)

5.中断 (24)

六、处理机控制指令 (26)

1.标志处理指令 (26)

2.其他处理机控制指令 (26)

用 Visual Studio 查看汇编代码 (27)

简要复习常用的汇编指令 (28)

堆栈相关指令 (28)

数据传送指令 (29)

跳转与比较指令 (30)

C 函数的参数传递过程 (30)

基础知识 (31)

函数调用规则 (31)

_cdecl C 调用规则: (31)

_stdcall 又称为 WINAPI,其调用规则: (31)

Pascal 调用规则: (32)

技术细节 (32)

代码分析 (34)

实例代码分析 (35)

浮点数编码: (42)

DOS 中断 (43)

1、字符功能调用类(Character-Oriented Function) (43)

2、目录控制功能(Directory-Control Function) (45)

3、磁盘管理功能(Disk-Management Function) (46)

4、文件操作功能(File Operation Function) (47)

5、文件操作功能(FCB)(File Operation Function) (51)

6、记录操作功能(Record Function) (52)

7、记录操作功能(FCB)(Record Function) (53)

8、内存分配功能(Memory-Allocation Function) (54)

9、系统功能(System Function) (55)

gcc中的内嵌汇编语言(INTEL i386平 台)

一.声明

虽然 Linux 的核心代码大部分是用 C 语言编写的,但是不可避免的其中还是有一部分 是用汇编语言写成的。有些汇编语言代码是直接写在汇编源程序中的,特别是 Linux 的启动 代码部分;还有一些则是利用 gcc 的内嵌汇编语言嵌在 C 语言程序中的。这篇文章简单介 绍了 gcc中的内嵌式汇编语言,主要想帮助那些才开始阅读 Linux 核心代码的朋友们

能够更快的入手。

这篇文章的主要信息来源是GNU的两个 info文件:https://www.sodocs.net/doc/d914531721.html,和 https://www.sodocs.net/doc/d914531721.html,,如果你觉得这 篇文章中的介绍还不够详细的话,你可以查阅这两个文件。当然,直接查阅这两个文件可以 获得更加权威的信息。 如果你不想被这两篇文档中的一大堆信息搞迷糊的话,我建议你先阅 读一下这篇文章,然后在必要时再去查阅更权威的信息。

二.简介

在 Linux 的核心代码中, 还是存在相当一部分的汇编语言代码。 如果你想顺利阅读 Linux 代码的话, 你不可能绕过这一部分代码。 在 Linux 使用的汇编语言代码中, 主要有两种格式: 一种是直接写成汇编语言源程序的形式,这一部分主要是一些 Linux 的启动代码;另一部分 则是利用 gcc的内嵌式汇编语言语句asm嵌在 Linux 的 C 语言代码中的。这篇文章主要是 介绍第二种形式的汇编语言代码。

首先,介绍一下 as支持的汇编语言的语法格式。大家知道,我们现在学习的汇编语言 的格式主要是INTEL风格的, 而在 Linux 的核心代码中使用的则是 A T&T格式的汇编语言代 码,应该说大部分人对这种格式的汇编语言还不是很了解,所以我觉得有必要介绍一下。接 着,我主要介绍一下 gcc的内嵌式汇编语言的格式。gcc的内嵌式汇编语言提供了一种在 C 语言源程序中直接嵌入汇编指令的很好的办法, 既能够直接控制所形成的指令序列,又有 着与 C 语言的良好接口,所以在 Linux 代码中很多地方都使用了这一语句。

三.AT&T的汇编语言语法格式

大部分人对INTEL格式的汇编语言都很了解了。但是,在 Linux 核心代码中,所有的汇 编语言指令都是用 A T&T格式的汇编语言书写的。这两种汇编语言在语法格式上有着很大 的不同:

1.在 A T&T的汇编语言中,用'$'前缀表示一个立即操作数;而在INTEL 的格式中,立即操 作数的表示不带任何前缀符。例如:下面两个语句 是完全相同的:

*A T&T: PUSH l $4

*INTEL: PUSH 4

2.A T&T和INTEL的汇编语言格式中,源操作数和目标操作数的位置正 好相反。INTEL的汇 编语言中,目标操作数在源操作数的左边;而在 A T&T的汇编语言中,目标操作数则在源 操作数的右边。例如:

*A T&T : addl $4,%eax

*INTEL: add eax,4

3.在 A T&T的汇编语言中, 操作数的字长是由操作码助记符的最后一个字母决定的, 后缀'b'、 'w'、'l'分别表示操作数的字长为 8 比特(字 节,byte),16 比特(字,word)和 32 比特(长 字,LONG),而 INTEL格式中操作数的字长是用“word ptr”或者“byte ptr”等前缀来表示的。 例如:

*A T&T: movb FOO,%al

*INTEL: mov al,byte ptr FOO

4.在 A T&T汇编指令中,直接远跳转/调用的指令格式是“lcall/ljmp$SECTION,$OFFSET”,同 样,远程返回的指令是“lret $STACK-ADJUST”;而在INTEL格式中,相应的指令分别为 “call/jmp far SECTION:OFFSET”和“ret far STACK-ADJUST”。

①A T&T汇编指令操作助记符命名规则

A T&T汇编语言中,操作码助记符的后缀字符指定了该指令中操作数的字长。后缀字母'b'、 'w'、'l'分别表示字长为 8 比特(字节,byte),16 比特(字,word)和 32 比特(长字,LONG) 的操作数。如果助记符中没有指定字长后缀并且该指令中没有内存操作数,汇编程序'as'会 根据指令中指定的寄存器操作数补上相应的后缀字符。所以,下面的两个指令具有相同的效 果(这只是GNU的汇编程序as 的一个特性,A T&T

的 Unix 汇编程序将没有字长后缀的指令的操作数字长假设为 32比特):

mov %ax,%bx

movw %ax,%bx

A T&T中几乎所有的操作助记符与INTEL格式中的助记符同名,仅有一小部分例外。操作数 扩展指令就是例外之一。在 A T&T汇编指令中,操作数扩展指令有两个后缀:一个指定源 操作数的字长,另一个指定目标操作数的字长。A T&T的符号扩展指令的基本助记符为

'movs',零扩展指令的基本助记符为'movz'(相应的INTEL指令为'movsx'和'movzx')。因此, 'movsbl %al,%edx'表示对寄存器 al 中的字节数据进行字节到长字的符号扩展, 计算结果存放 在寄存器 edx 中。下面是一些允许的操作数扩展后缀:

*bl: 字节->长字

*bw: 字节->字

*wl: 字->长字

还有一些其他的类型转换指令的对应关系:

*INTEL *A T&T

⑴ cbw cbtw 符号扩展:al->ax

⑵ cwde cwtl 符号扩展:ax->eax

⑶ cwd cwtd 符号扩展:ax->dx:ax

⑷ cdq cltd 符号扩展:eax->edx:eax

还有一个不同名的助记符就是远程跳转/调用指令。在INTEL格式中,远程跳转/调用指令的 助记符为“call/jmp far”,而在 A T&T的汇编 语言中,相应的指令为“lcall”和“ljmp”。

②A T&T中寄存器的命名在 A T&T汇编语言中,寄存器操作数总是以'%'作为前缀。80386芯 片的寄存器包括:

⑴ 8 个 32 位寄存器:'%eax', '%ebx','%ecx', '%edx', %edi', '%esi', '%ebp', %esp'

⑵ 8 个 16 位寄存器:'%ax','%bx', '%cx', '%dx', '%si', '%di', %bp', '%sp'

⑶ 8 个 8 位寄存器:'%ah', %al',%bh', '%bl', '%ch', '%cl', %dh', %dl'

⑷ 6 个段寄存器: '%cs', %ds', '%es', '%ss', '%fs', '%gs'

⑸ 3 个控制寄存器: '%cr0', '%cr1', ' %cr2'

⑹ 6 个调试寄存器: '%db0', '%db1', '%db2', '%db3', '%db6', '%db7'

⑺ 2 个测试寄存器: '%tr6', '%tr7'

⑻ 8 个浮点寄存器栈:'%st(0)',‘%st(1)','%st(2)', '%st(3)', '%st(4)', '%st(5)',%st(6)',%st(7)'

*注:我对这些寄存器并不是都了解,这些资料只是摘自 https://www.sodocs.net/doc/d914531721.html,文档。如果真的需要寄存器 命名的资料,我想可以参考一下相应GNU工具的机器描述方面的源文件。

③A T&T中的操作码前缀

⑴段超越前缀'cs','ds','es','ss','fs','gs':当汇编程序中对内存操作数进行

SECTION:MEMORY-OPERAND引用时,自动加上相应的段超越前缀。

⑵操作数/地址尺寸前缀'data16','addr16':这些前缀将32 位的操作数/地址转化为 16 位的操作 数/地址。

⑶总线锁定前缀'LOCK':总线锁定操作。'LOCK'前缀在 Linux 核心代码中使用很多,特别是 SMP 代码中。

⑷协处理器等待前缀'wait':等待协处理器完成当前操作。

⑸指令重复前缀'rep','repe','repne':在串操作中重复指令的执行。

④A T&T中的内存操作数

在INTEL的汇编语言中,内存操作数引用的格式如下:

SECTION:[BASE + INDEX*SCALE + DISP]

而在 A T&T的汇编语言中,内存操作数的应用格式则是这样的:

SECTION: DISP(BASE,INDEX,SCALE)

下面是一些内存操作数的例子:

*A T&T *INTEL

⑴ -4 (%ebp) [ebp-4]

⑵ foo(,%eax,4) [foo+eax*4]

⑶ foo(,1) [foo]

⑷ %gs: foo gs: foo

还有,绝对跳转/调用指令中的内存操作数必须以'*'最为前缀,否则 as总是假设这是一个相对 跳转/调用指令。

⑤A T&T中的跳转指令

as 汇编程序自动对跳转指令进行优化,总是使用尽可能小的跳转偏移量。如果 8 比特的 偏移量无法满足要求的话,as 会使用一个 32 位的偏移量,as 汇编程序暂时还不支持 16 位的 跳转偏移量,所以对跳转指令使用'addr16'前缀是无效的。还有一些跳转指令只支持 8位的跳 转偏移量,这些指令包括:'jcxz', 'jecxz','loop','loopz','loope','loopnz'和'loopne'。所以,在 as 的 汇编源程序中使用这些指令可能会出错。(幸运的是,gcc并不使用这些指令)

对 A T&T汇编语言语法的简单介绍差不多了,其中有些特性是as 特有的。在 Linux 核心代码 中,并不涉及到所有上面这些提到的语法规则,其中有两点规则特别重要:第一,as 中对寄存 器引用时使用前缀'%';第二,A T&T汇编语言中源操作数和目标操作数的位置与我们熟悉的 INTEL 的语法正好相反。

四.gcc的内嵌汇编语言语句 asm

利用 gcc的 asm语句,你可以在 C 语言代码中直接嵌入汇编语言指令,同时还可以使 用 C 语言的表达式指定汇编指令所用到的操作数。这一特性提供了很大的方便。要使用这一 特性,首先要写一个汇编指令的模板(这种模板有点类似于机器描述文件中的指令模板),然 后要为每一个操作数指定一个限定字符串。例如:

extern __inline__ void change_bit(int nr,volatile void *addr)

{

__asm__ __volatile__( LOCK_PREFIX "btcl %1,%0" :"=m" (ADDR) :"ir" (nr))?

}

上面的函数中:

LOCK_PREFIX:这是一个宏,如果定义了__SMP__,扩展为"LOCK?",

用于指定总线锁定前缀,否则扩展为""。

ADDR:这也是一个宏,定义为(*(volati

8086/8088指令详解

浮点指令在《Art of ASM》的PDF电子书中有详细说明,

https://www.sodocs.net/doc/d914531721.html,/download/art-of-asm.zip

当然,Intel的PDF指令手册是最权威的。

Intel Architecture Software Developer's Manual, Volume 1: Basic Architecture

https://www.sodocs.net/doc/d914531721.html,/design/pentium/manuals/24319001.pdf

Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual

https://www.sodocs.net/doc/d914531721.html,/design/pentium/manuals/24319101.pdf

Intel architecture Software Developer's Manual, Volume 3: System Programming Guide

https://www.sodocs.net/doc/d914531721.html,/design/pentium/manuals/24319201.pdf

一、数据传送指令

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寄存器中.该指令常指定 DI寄存器.

4.标志寄存器传送指令

LAHF(Load AH with flags)标志送 AH

SAHF(store AH into flags)AH送标志寄存器 PUSHF(push the flags) 标志进栈

POPF(pop the flags) 标志出栈

.LAHF 标志送 AH

格式为: LAHF

执行的操作:(AH)<-(PWS 的低字节)

.SAHF AH 送标志寄存器

格式为: SAHF

执行的操作:(PWS的低字节)<-(AH)

.PUSHF 标志进栈

格式为: PUSHF

执行的操作:(SP)<-(SP)-2

((SP)+1,(SP))<-(PSW)

.POPF 标志出栈

格式为: POPF

执行的操作:(PWS)<-((SP)+1,(SP))

(SP)<-(SP+2)

二、算术指令

1.加法指令

ADD(add)加法

ADC(add with carry)带进位加法

INC(increment)加 1

.ADD 加法指令

格式: ADD DST,SRC

执行的操作:(DST)<-(SRC)+(DST)

.ADC 带进位加法指令

格式: ADC DST,SRC

执行的操作:(DST)<-(SRC)+(DST)+CF

.ADD 加 1指令

格式: INC OPR

执行的操作:(OPR)<-(OPR)+1

2.减法指令

SUB(subtract)减法

SBB(subtract with borrow)带借位减法

DEC(Decrement)减 1

NEG(Negate)求补

CMP(Compare)比较

.SUB 减法指令

格式: SUB DST,SRC

执行的操作:(DST)<-(DST)-(SRC)

.SBB 带借位减法指令

格式: SBB DST,SRC

执行的操作:(DST)<-(DST)-(SRC)-CF

.DEC 减 1指令

格式: DEC OPR

执行的操作:(OPR)<-(OPR)-1

.NEG 求补指令

格式: NEG OPR

执行的操作:(OPR)<- -(OPR)

.CMP 比较指令

格式: CMP OPR1,OPR2

执行的操作:(OPR1)-(OPR2)

该指令与 SUB 指令一样执行减法操作,但不保存结果,只是根据结果设置条件标志 西半球.

3.乘法指令

MUL(Unsigned Multiple)无符号数乘法

IMUL(Signed Multiple)带符号数乘法

.MUL 无符号数乘法指令

格式: MUL SRC

执行的操作:

字节操作数:(AX)<-(AL)*(SRC)

字操作数:(DX,AX)<-(AX)*(SRC)

.IMUL 带符号数乘法指令

格式: IMUL SRC

执行的操作:与 MUL相同,但必须是带符号数,而 MUL 是无符号数.

4.除法指令

DIV(Unsigned divide)无符号数除法

IDIV(Signed divide)带符号数除法

CBW(Convert byte to word)字节转换为字

CWD(Contert word to double word)字转换为双字

.DIV 无符号数除法指令

格式: DIV SRC

执行的操作:

字节操作:(AL)<-(AX)/(SRC)的商

(AH)<-(AX)/(SRC)的余数

字操作: (AX)<-(DX,AX)/(SRC)的商

(AX)<-(DX,AX)/(SRC)的余数

.IDIV 带符号数除法指令

格式: DIV SRC

执行的操作:与 DIV相同,但操作数必须是带符号数,商和余数 也均为带符号数,且余数的符号与被除数的符号相同.

.CBW 字节转换为字指令

格式: CBW

执行的操作:AL的内容符号扩展到 AH.即如果(AL)的最高有效 位为 0,则(AH)=00?如(AL)的最高有效位为 1,则(AH)=0FFH

.CWD 字转换为双字指令

格式: CWD

执行的操作:AX的内容符号扩展到 DX.即如(AX)的最高有效位 为 0,则(DX)=0?否则(DX)=0FFFFH.

这两条指令都不影响条件码.

三、逻辑指令

1.逻辑运算指令

AND(and) 逻辑与

OR(or) 逻辑或

NOT(not) 逻辑非

XOR(exclusive or)异或

TEST(test) 测试

.AND 逻辑与指令

格式: AND DST,SRC

执行的操作:(DST)<-(DST)^(SRC)

.OR 逻辑或指令

格式: OR DST,SRC

执行的操作:(DST)<-(DST)V(SRC)

.NOT 逻辑非指令

格式: NOT OPR

执行的操作:(OPR)<-(OPR)

.XOR 异或指令

格式: XOR DST,SRC

执行的操作:(DST)<-(DST)V(SRC)

.TEST 测试指令

格式: TEST OPR1,OPR2

执行的操作:(DST)^(SRC)

两个操作数相与的结果不保存,只根据其特征置条件码

2.移位指令

SHL(shift logical left) 逻辑左移

SAL(shift arithmetic left) 算术左移

SHR(shift logical right) 逻辑右移

SAR(shift arithmetic right) 算术右移

ROL(Rotate left) 循环左移

ROR(Rotate right) 循环右移

RCL(Rotate left through carry) 带进位循环左移

RCR(Rotate right through carry) 带进位循环右移

格式: SHL OPR,CNT(其余的类似)

其中 OPR可以是除立即数以外的任何寻址方式.移位次数由 CNT决定,

CNT可以是 1或 CL.循环移位指令可以改变操作数中所有位的位置?移

位指令则常常用来做乘以 2除以 2操作.其中算术移位指令适用于带符

号数运算,SAL用来乘 2,SAR用来除以 2?而逻辑移位指令则用来无符

号数运算,SHL用来乘 2,SHR用来除以 2.

四、串处理指令

1.与 REP相配合工作的 MOVS,STOS和 LODS指令

.REP重复串操作直到(CX)=0为上

格式: REP string primitive

其中 String Primitive 可为 MOVS,LODS 或 STOS 指令

执行的操作:

1)如(CX)=0则退出 REP,否则往下执行.

2)(CX)<-(CX)-1

3)执行其中的串操作

4)重复 1)~3)

.MOVS 串传送指令

格式:可有三种

MOVS DST,SRC

MOVSB(字节)

MOVSW(字)

其中第二、三种格式明确地注明是传送字节或字,第一种格式则应 在操作数中表明是字还是字节操作,例如:

MOVS ES:BYTE PTR[DI],DS:[SI]

执行的操作:

1)((DI))<-((SI))

2)字节操作:

(SI)<-(SI)+(或-)1,(DI)<-(DI)+(或-)1

当方向标志 DF=0时用+,当方向标志 DF=1 时用-

3)字操作:

(SI)<-(SI)+(或-)2,(DI)<-(DI)+(或-)2

当方向标志 DF=0时用+,当方向标志 DF=1 时用-

该指令不影响条件码.

.CLD(Clear direction flag)该指令使 DF=0,在执行串操作

指令时可使地址自动增量?

.STD(Set direction flag)该指令使 DF=1,在执行串操作指

令时可使地址自动减量.

.STOS 存入串指令

格式: STOS DST

STOSB(字节)

STOSW(字)

执行的操作:

字节操作:((DI))<-(AL),(DI)<-(DI)+-1

字操作: ((DI))<-(AX),(DI)<-(DI)+-2

该指令把AL或AX的内容存入由(DI)指定的附加段的某单元中,并根据DF的值及数据 类型修改 DI的内容,当它与REP联用时,可把 AL或AX的内容存入一个长度为(CX)的缓冲 区中.

.LODS 从串取指令

格式: LODS SRC

LODSB

LODSW

执行的操作:

字节操作:(AL)<-((SI)),(SI)<-(SI)+-1

字操作: (AX)<-((SI)),(SI)<-(SI)+-2

该指令把由(SI)指定的数据段中某单元的内容送到AL或AX中,并根据方向标志及数据 类型修改 SI的内容.指令允许使用段跨越前缀来指定非数据段的存储区.该指令也不影响条 件码.一般说来,该指令不和REP联用.有时缓冲区中的一串字符需要逐次取出来测试时,可使 用本指令.

2.与 REPE/REPZ和 REPNZ/REPNE联合工作的 CMPS和 SCAS 指令

.REPE/REPZ 当相等/为零时重复串操作

格式: REPE(或 REPZ) String Primitive

其中 String Primitive 可为 CMPS 或 SCAS 指令.

执行的操作:

1)如(CX)=0或 ZF=0(即某次比较的结果两个操作数不等)时退出,

否则往下执行

2)(CX)<-(CX)-1

3)执行其后的串指令

4)重复 1)~3)

.REPNE/REPNZ 当不相等/不为零时重复串操作

格式: REPNE(或 REPNZ) String Primitive

其中 String Primitive 可为 CMPS 或 SCAS 指令

执行的操作:

除退出条件(CX=0)或 ZF=1外,其他操作与 REPE 完全相同.

.CMPS 串比较指令

格式: CMP SRC,DST

CMPSB

CMPSW

执行的操作:

1)((SI))-((DI))

2)字节操作:(SI)<-(SI)+-1,(DI)<-(DI)+-1

字操作: (SI)<-(SI)+-2,(DI)<-(DI)+-2

指令把由(SI)指向的数据段中的一个字(或字节)与由(DI)指向的附加段中的一个字(或字 节)相减,但不保存结果,只根据结果设置条件码,指令的其它特性和 MOVS 指令的规定相同.

.SCAS 串扫描指令

格式: SCAS DST

SCASB

SCASW

执行的操作:

字节操作:(AL)-((DI)),(DI)<-(DI)+-1

字操作: (AL)-((DI)),(DI)<-(DI)+-2

该指令把 AL(或 AX)的内容与由(DI)指定的在附加段中的一个字节(或字)进行比较,并 不保存结果,只根据结果置条件码.指令的其他特性和MOVS 的规定相同.

五、控制转移指令

1.无条件转移指令

.JMP(jmp) 跳转指令

1)段内直接短转移

格式:JMP SHORT OPR

执行的操作:(IP)<-(IP)+8位位移量

2)段内直接近转移

格式:JMP NEAR PTR OPR

执行的操作:(IP)<-(IP)+16位位移量

3)段内间接转移

格式:JMP WORD PTR OPR

执行的操作:(IP)<-(EA)

4)段间直接(远)转移

格式:JMP FAR PTR OPR

执行的操作:(IP)<-OPR的段内偏移地址

(CS)<-OPR所在段的段地址

5)段间间接转移

格式:JMP DWORD PTR OPR

执行的操作:(IP)<-(EA)

(CS)<-(EA+2)

汇编语言 快速入门

“哎哟,哥们儿,还捣鼓汇编呢?那东西没用,兄弟用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):指

汇编语言知识大全

第一章基础知识: 一.机器码: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

6、汇编学习从入门到精通(荐书)

汇编学习从入门到精通Step By Step 2007年12月15日星期六00:34 信息来源:https://www.sodocs.net/doc/d914531721.html,/hkbyest/archive/2007/07/22/1702065.aspx Cracker,一个充满诱惑的词。别误会,我这里说的是软件破解,想做骇客的一边去,这年头没人说骇客,都是“黑客”了,嘎嘎~ 公元1999年的炎热夏季,我捧起我哥留在家的清华黄皮本《IBM-PC汇编语言程序设计》,苦读。一个星期后我那脆弱的小心灵如玻璃般碎裂了,为了弥补伤痛我哭爹求妈弄了8k大洋配了台当时算是主流的PC,要知道那是64M内存!8.4G硬盘啊!还有传说中的Celeon 300A CPU。不过很可惜的是在当时那32k小猫当道的时代,没有宽带网络,没有软件,没有资料,没有论坛,理所当然我对伟大的计算机科学体系的第一步探索就此夭折,此时陪伴我的是那些盗版光盘中的游戏,把CRACK_XXX文件从光盘复制到硬盘成了时常的工作,偶尔看到光盘中的nfo 文件,心里也闪过一丝对破解的憧憬。 上了大学后有网可用了,慢慢地接触到了一些黑客入侵的知识,想当黑客是每一个充满好奇的小青年的神圣愿望,整天看这看那,偷偷改了下别人的网页就欢喜得好像第一次偷到鸡的黄鼠狼。 大一开设的汇编教材就是那不知版了多少次的《IBM-PC汇编语言程序设计》,凭着之前的那星期苦读,考试混了个80分。可惜当时头脑发热,大学60分万岁思想无疑更为主流,现在想想真是可惜了宝贵的学习时间。 不知不觉快毕业了,这时手头上的《黑客防线》,《黑客X档案》积了一大摞,整天注来注去的也厌烦了,校园网上的肉鸡一打一打更不知道拿来干什么。这时兴趣自然转向了crack,看着杂志上天书般的汇编代码,望望手头还算崭新的汇编课本,叹了口气,重新学那已经忘光了的汇编语言吧。咬牙再咬牙,看完寻址方式那章后我还是认输,不认不行啊,头快裂了,第三次努力终告失败。虽然此时也可以爆破一些简单的软件,虽然也知道搞破解不需要很多的汇编知识,但我还是固执地希望能学好这门基础中的基础课程。 毕业了,进入社会了,找工作,上班,换工作成了主流旋律,每天精疲力尽的哪有时间呢?在最初的中国移动到考公务员再到深圳再到家里希望的金融机构,一系列的曲折失败等待耗光了我的热情,我失业了,赋闲在家无所事事,唯一陪伴我的是那些杂志,课本,以及过时的第二台电脑。我不想工作,我对找工作有一种恐惧,我靠酒精麻醉自己,颓废一段日子后也觉得生活太过无聊了,努力看书考了个CCNA想出去,结果还是被现实的就业环境所打败。三年时间,一无所获。 再之后来到女朋友处陪伴她度过刚毕业踏入社会工作的适应时期,这段时间随便找了个电脑技术工作,每月赚那么个几百块做生活费。不过这半年让我收获比较大的就是时间充裕,接触到了不少新东西,我下定决心要把汇编学好,这时我在网上看到了别人推荐的王爽《汇编语言》,没抱什么希望在当当网购了人生中的第一次物,19块6毛,我记得很清楚,呵呵。 废话终于完了,感谢各位能看到这里,下面进入正题吧。

Windows汇编语言程序设计基础

第1章Windows汇编语言程序设计基础 Windows汇编语言程序分为控制台编程和图形界面编程两种,控制台编程相对简单一些。为了由浅入深,本书从控制台编程开始讲解。 读者总希望用最快的速度掌握书中的概貌,为此从一个最简单的程序开始。一些汇编语言语法也结合程序进行讲解,有些指令和语法用注解的方法说明。 1.1 第一个完整的Windows汇编语言程序 Windows汇编语言程序有自己的编程规范,它的编程规范比Visual C要简单得多,调试也很方便。更重要的是系统把重要的东西都呈现给读者,使读者更能掌握其中的本质。 用一条一条的汇编语言指令很难写出大程序,Windows汇编语言程序也是调用系统提供的API来写程序。因而,用Windows汇编语言同样可写出大程序。以下是一个最简单的Windows程序。 ;程序功能:显示一个信息框。 ;ex1.asm(e:\masm\base) ;程序名 ;编译链接方法: ;ml /c /coff ex1.asm ;link /subsystem:console ex1.obj .386 ;指明指令集 .model flat,stdcall ;程序工作模式,flat为Windows程序使用的模式(代码和数据 ;使用同一个4GB段),stdcall为API调用时右边的参数先入栈option casemap:none ;指明大小写敏感 include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib .data ;数据段 szCaption db '抬头串',0 szText db 'Hello!',0 .code ;代码段 start:

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上安装了

汇编语言入门

汇编语言入门教程 对初学者而言,汇编的许多命令太复杂,往往学习很长时间也写不出一个漂漂亮亮的程序,以致妨碍了我们学习汇编的兴趣,不少人就此放弃。所以我个人看法学汇编,不一定要写程序,写程序确实不是汇编的强项,大家不妨玩玩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),有九个有意义的标志,将在下文用到时详细说明。 内存是电脑运作中的关键部分,也是电脑在工作中储存信息的地方。内存组织有许多可存放

汇编语言基础知识

汇编语言基础知识 汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件系统的结构,才能有 效地应用汇编语言对其编程,因此,本章对硬件系统结构的问题进行部分探讨,首先介绍了计算机的基本结构、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 个内存单 元。

快速入门单片机汇编语言

快速入门单片机汇编语 言 文档编制序号:[KKIDT-LLE0828-LLETD298-POI08]

快速入门单片机汇编语言 简要: 单片机有通用型和专用型之分。专用型是厂家为固定程序的执行专门开发研制的一种单片机,其程序不可更改。通用型单片机是常用的一种供学习或自主编制程序的单片机,其程序需要自己写入,可更改。单片机根据其基本操作处理位数不同可以分为:1位、4位、8位、16、32位单片机。 正文: 在此我们主要讲解美国ATMEL公司的89C51单片机。 一、89C51单片机PDIP(双列直插式)封装引脚图: 其引脚功能如下: P0口(—):为双向三态口,可以作为输入/输出口。但在实际应用中通常作为地址/数据总线口,即为低8位地址/数据总线分时复用。低8位地址在ALE信号的负跳变锁存到外部地址锁存器中,而高8位地址由P2口输出。 P1口(—):其每一位都能作为可编程的输入或输出线。 P2口(—):每一位也都可作为输入或输出线用,当扩展系统外设时,可作为扩展系统的地址总线高8位,与P0口一起组成16位地址总线。对89c51单片机来说,P2口一般只作为地址总线使用,而不作为I/O线直接与外设相连。 P3口(—):其为双功能口,作为第一功能使用时,其功能与P1口相同。当作为第二功能使用时,每一位功能如下表所示。 P3口第二功能

Rst\Vpd:上电复位端和掉电保护端。 XTAL1(xtal2):外接晶振一脚,分别接晶振的一端。 Gnd:电源地。 Vcc:电源正级,接+5V。 PROG\ALE:地址锁存控制端 PSEN:片外程序存储器读选通信号输出端,低电平有效。 EA\vpp:访问外部程序储存器控制信号,低电平有效。当EA为高电平时访问片内存储器,若超出范围则自动访问外部程序存储器。当EA为低电平时只访问外部程序存储器。 二、常用指令及其格式介绍: 1、指令格式: [标号:]操作码 [ 目的操作数][,操作源][;注释] 例如:LOOP:ADD A,#0FFH ;(A)←(A)+FFH 2、常用符号: Ri和Rn:R表示工作寄存器,i表示1和0,n表示0~7。 rel:相对地址、地址偏移量,主要用于无条件相对短转移指令和条件转移指令。 #data:包含于指令中的8位立即数。 #data16:包含于指令中的16位立即数。

汇编语言入门教程

汇编语言入门教程 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),有九个有意义的标志,将在下文用到时详细说明。

汇编语言实现简单的计算器运算

汇编语言实现简单的计算器运算 DA TAS SEGMENT x dw 0 op db 0 DIV ARRAY dw 10000,1000,100,10,1 DA TAS ENDS stack segment db 100 dup(?) stack ends CODES SEGMENT ASSUME CS:CODES,DS:DA TAS,ss:stack START: MOV AX,DATAS MOV DS,AX next: call do_cal ;输入第一个表达式如:5+3= call show ;输出表达式结果 mov dl,0dh mov ah,02h int 21h mov dl,0ah mov ah,02h int 21h ;回车换行 jmp next ;跳回输入第二个表达式 do_cal: ;输入表达式 call input ;输入数 cmp al,'e' jz exit MOV OP,AL CMP OP,'+' jnz next1 call do_add jmp next5 next1: CMP OP,'-' JNZ NEXT2 CALL DO_SUB JMP NEXT5 NEXT2: CMP OP,'*' JNZ NEXT3 CALL DO_MUL JMP NEXT5 NEXT3:

CMP OP,'/' JNZ NEXT4 CALL DO_DIV jmp next5 NEXT4: cmp op,'=' call show next5:ret ;判断运算符input: ;输入数字xor bx,bx mov cx,10 skip: MOV AH,1 INT 21H cmp al,'0' jl skip1 cmp al,'9' jg skip1 push ax mov ax,bx mul cx mov bx,ax pop ax and al,0fh xor ah,ah add bx,ax jmp skip skip1:ret do_add: ;加法 mov x,bx call input ;输入第二个数 add bx,x ret do_sub: ;减法 mov x,bx call input ;输入第二个数 sub x,bx mov bx,x ret do_mul: ;乘法 mov x,bx call input ;输入第二个数 mov ax,bx mul x mov bx,ax

汇编语言基础练习题目

一、填空 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。以后每一个字单元的地址在前一个的基

汇编语言实现冒泡排序(一)

;用汇编语言实现实现冒泡排序,并将排序后的数输出 DATAS SEGMENT A dw 100,344,3435,43433,3438,343,134,80,8,1000,65535,54,45 N=$-A ;计算数字所占的字节数 DATAS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS START:MOV AX,DATAS MOV DS,AX MOV SI,0 ;SI遍历数字;前一个数的地址 MOV CX,N/2-1 ;设置循环次数,M(M=N/2)个数需要,循环M-1次 CALL BUBBLE ;调用BUBBLE将原来的数排序 ;输出排序后的数 MOV CX,N/2 ;循环M次输出排序后的M个数 MOV SI,0 ;SI遍历排序后的数 MOV DI,0 ;用DI记录数字的位数 MOV BP,N+5 ;BP用于遍历存储的转化后的字符的位置 SHOW: PUSH CX ;循环次数入栈 MOV DX,0 ;由于将要进行16位除需要置高16位为0 MOV AX,[SI] ;低16位为排序后的数 CALL DTOC ;调用DTOC将十进制数转换为字符串 CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出ADD SI,2 ;下一个数 POP CX ;循环次数出栈栈 LOOP SHOW MOV AH,4CH INT 21H ;冒泡排序 BUBBLE PROC L1: PUSH CX ;将循环次数入栈 LEA SI,A ;SI遍历DATAS数据段的数字 L2: MOV AX,A[SI] ;将前一个数存于AX CMP AX,A[SI+2] ;比较前后两个数 JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较XCHG AX,A[SI+2] ;否则,交换前后两个数的位置 MOV A[SI],AX NEXT:ADD SI,2 ;下一个数 LOOP L2 ;注意内层循环的次数已经确定了 POP CX ;将循环次数出栈 LOOP L1 ;下一轮比较 RET BUBBLE ENDP

计算机基础知识汇编

计算机基础知识汇编 第一讲计算机的概述及数据单位 (2) 第二讲计算机系统组成 (4) 第三讲计算机主要性能指标和系统配置 (5) 第四讲 word基本知识 (7) 第五讲 Excel电子表格基本知识点 (11) 第六讲网络类型及分类方法 (14) 第七讲计算机病毒 (15) 第八讲信息安全 (16) 第一讲计算机的概述及数据单位

一、什么是计算机 电子计算机(Computer)是一台自动、可靠、能高速运算的机器,由于它能作为人脑的延伸和发展,所以我们又把计算机称为电脑,它能够自动进行数值计算、信息处理、自动化管理等多个方面的工作。 二、计算机的发展阶段 世界上第一台电子计算机是1946年由美国宾夕法尼亚大学研制成功,名为埃尼阿克(ENIAC),重量30吨,占地面积170平方米,运算速度为5000次/秒。 计算机的发展经历了四代: 第一代:1946年----1957年,以电子管为主要标志; 第二代:1958年----1964年,以晶体管为主要标志; 第三代:1965年----1969年,以中、小规模集成电路为主要标志; 第四代:1970年----至今,以大规模和超大规模集成电路为主要标志。 目前计算机正向微型化、网络化、智能化发展。 三、计算机的特点 1、高速运算能力和检索能力。目前的计算机运算能力已达到10亿次/秒。 2、强存储记忆能力。能存储大量的原始数据、中间结果及程序。 3、很高的计算精度和可靠性。计算机精度可达几百位,连续无故障时间可达几年。 4、具有逻辑判断能力。能进行数据的比较、分类、排序、检索等。 5、工作全部自动进行。只要给计算机发出指令,计算机将按着指令自动执行。 四、计算机的应用领域

汇编语言基础试题

第一章基本知识 一、单项选择题(共40分,每题2分) 1.若十进制数为13 2.75,则其十六进制数为(B) A.21.3 B.84.C C.4.6 D.6 2.若[X补]=11111,则其十进制真值为(C) A.-31 B.-15 C.-1 D.31 3.某定点整数64位,含1位符号位,补码表示,则其绝对值最大负数为(A) A.-263 B.-264 C.-(263-1) D.-(263-1) 4.原码乘法是(D) A.用原码表示操作数,然后直接相乘 B.被乘数用原码表示,乘数取绝对值,然后相乘 C.乘数用原码表示,被乘数取绝对值,然后相乘 D.先取操作数绝对值相乘,符号位单独处理 5.在微机系统中分析并控制指令执行的部件是(C) A.寄存器 B.数据寄存器 C.CPU D.EU 6.已知X=76,则[X]补=(B) A.76H B.4CH C.0B4H D.0CCH 7.已知[X]补=80H, 则X=(D) A.80H B.0 C.0FFH D.-80H 8.已知[X]补=98H, 则[X]补/2=(A) A.0CCH B.4CH C.49H D.31H 9.已知X=78,Y=-83则[X+Y]补=(C) A.0F5H B.0A1H C.0FBH D.65H 10.在计算机的CPU中执行算术逻辑运算的部件是(A) A.ALU B.PC C.AL D.AR 11.将125转换成二进制数的结果(A) A.7DH B.7CH C.7EH D.7BH 12.将93H看成一个组合BCD码,其结果是(B) A.10010101 B.10010011 C.10000011 D.10000001 13.能被计算机直接识别的语言是(C) A.C语言 B.汇编语言 C.机器语言 D.面向对象语言

汇编语言入门教程

汇编语言入门教程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

80X86汇编语言程序设计 第一章基础知识

80X86汇编语言程序设计 第一章基础知识(1.2.) 一.进制转换: (1)十进制转换成二进制:除2取余法 (2)十进制转换成十六进制:除16取余法 (3)二进制转换成十进制:权的展开式,各位二进制数码乘以与其对应的权之和 (4)十六制转转换成十进制:权的展开式,各位十六进制数码乘以与其对应的权之和 (5)二进制转换成十六进制:四位归一法(8421码),把二进制数码从低位到高位每4位组成一组,直接用十六进制数来表示 (6)十六进制转换成二进制:一位分四法(8421码),把十六进制数中的每一位用4位二进制数表示,就形成相应的二进制数 二.数据的表示 (1)数的补码表示(有符号数) 把一个数连同其符号在内在机器中的表示加以数值化,这样的数称为机器数。一般用最高有效位来表示数的符号。正数用0表示,负数用1表示。机器数可以用不同的码制来表示,常用的有原码、补码和反码表示法。 补码表示法中,正数采用符号绝对值表示;负数X用2的n次方-X来表示,其中n位机器的字长。 0的补码就是00000000 8位表示数的有符号整数的范围为:-128~+127. 16位表示数的有符号整数的范围为:-32768~+32767. 例如:机器字长为16位,写出N=-117D的补码表示 +117D可表示为:0000 0000 0111 0101 按位求反后为: 1111 1111 1000 1010 末位加1后为: 1111 1111 1000 1011 十六进制数为: F F 8 B N=-117D的补码是FF8BH (2)无符号数 8位表示数的无符号整数的范围为:0~255(256-1). 16位表示数的无符号整数的范围为:0~65535(65536-1). (3)符号扩展 当要扩展的数是无符号数时,只要在最高位前扩展(m-n)个0。 如果要扩展的数是有符号数,并且采用补码形式表示,进行符号扩展。(正数前面用0补齐;负数

汇编语言实战经验

汇编语言实战经验 “ 哎哟,哥们儿,还捣鼓汇编呢?那东西没用,兄弟用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的情

相关主题