【Win32汇编】学习Win32汇编
学习Win32汇编(Windows下的32位汇编)
第一个程序Hello world
控制台输出(新建Console App工程)
Debug输出(新建Win32 App工程)
后面代码的头文件在这里
伪指令DUP与数组
运算符
子过程(函数)的传参与调用
获取数组长度和字节数等
数据对齐
获取变量地址以及伪指令this的使用
loop的使用
堆栈以及相关指令
二进制相关函数
标志寄存器
数据传送指令
逻辑运算指令
位测试与位扫描指令
移位指令
符号扩展指令
加减指令
乘除指令
跳转指令
串指令
条件及循环伪指令
结构体
书籍推荐
- Windows环境下32位汇编语言程序设计(典藏版)
- 链接:https://pan.baidu.com/s/1XLkMW177ySxt9YUUnqQ9tw
- 提取码:k10i
- 环境配置
- 方案一
- 自己体会
- 方案二(推荐)
- 链接:https://pan.baidu.com/s/170AUzz4yyGWGit9f_vs3eA
- 提取码:u3u3
- 方案一
- 参考博客
- 万一的Delphi博客
基础篇
第一个程序Hello world
;模式定义
.386 ;汇编伪指令,指明了程序使用80386指令集
.model flat, stdcall ;汇编伪指令,指明了程序工作模式,Win32程序只有一种内存模式,即flat。stdcall指明了编译器参数传递的约定,即函数调用时,实参入栈从右往左。
option casemap:none ;指明标识符区分大小写
;引入头文件和库文件,inc文件主要包含函数或常量的声明,lib文件包含了动态库函数的地址信息和静态库的函数代码
include windows.inc ;windows.inc包含着Win32程序用到的常量、结构的声明,下面用到的MB_OK常量就是在其中声明
include user32.inc
include kernel32.inc
includelib user32.lib ;user32.dll是用户服务接口, 负责消息管理等,MessageBox函数来自user32.dll
includelib kernel32.lib ;kernel32.dll是系统服务接口, 负责内存管理等,ExitProcess函数来自kernel32.dll
;数据段(.data表示已初始化的数据)
.dataszCaption db 'Hi', 0szMsg db 'Hello World!', 0 ;定义字符串变量,0表示字符串结尾
;代码段
.code
start:invoke MessageBox, NULL, addr szMsg, addr szCaption, MB_OK invoke ExitProcess, NULL ;invoke是调用函数的伪指令,MessageBox(显示消息框)和ExitProcess(退出程序)为API函数
end start
控制台输出(新建Console App工程)
.386
.model flat, stdcall
option casemap:noneinclude msvcrt.inc
includelib msvcrt.lib.dataszFmt db 'EAX=%d; ECX=%d; EDX=%d', 0.code
start:mov eax, 11mov ecx, 22mov edx, 33invoke crt_printf, addr szFmt, eax, ecx, edx ;crt_printf就是C语言里面的printf函数ret ;ret是用于子程序返回的指令。在没有生成Win32窗口时可以使用ret代替ExitProcess
end start
Debug输出(新建Win32 App工程)
.386
.model flat, stdcall
option casemap:noneinclude windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib.dataszText db 'Hello World!', 0.code
start:PrintLine ;----------------------------------------PrintString szText ;Hello World!PrintLine ;----------------------------------------ret
end start
后面代码的头文件在这里
.386
.model flat, stdcall
option casemap :noneinclude windows.inc
include kernel32.inc
include user32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib user32.lib
includelib masm32.lib
includelib debug.lib
伪指令DUP与数组
;数组的实现
.data;初始化数组,每个数组元素大小为2个字节val dw 11,22,33
.code
start:lea ebx, val ;等价于mov ebx,offset valmov esi, type val ;每个元素大小为2个字节xor ax, axmov ax, word ptr [ebx+esi*0]PrintDec ax ;11;也可以使用movzx eax,word ptr [ebx+esi*1];也可以使用mov ax, word ptr [ebx][esi*1]或者mov ax, word ptr val[esi*1]mov ax, word ptr [ebx+esi*1]PrintDec ax ;22mov ax, word ptr [ebx+esi*2]PrintDec ax ;33ret
end start
;伪指令DUP的使用
.data?v1 dd 4096 dup(?) ;未初始化变量应该放在.data?段,如果放在.data段,在生成exe文件时会多占4096*4字节的内存
.datav2 dd 2 dup(1,2,3)
.code
start:DumpMem offset v2, 24 ;01000000-02000000-03000000-01000000-02000000-03000000共24字节ret
end start
运算符
.code
start:;注意:下面这些运算符都是伪指令,在80386中由编译器执行。而在Dos中它们有对应字节码,由CPU执行。;算数运算符PrintDec 7 / 3 ;2;关系操作符:eq(=),ne(!=),lt(<),le(<=),gt(>),ge(>=),满足条件输出-1,否则输出0PrintDec 2 eq 1 ;0PrintDec 2 eq 2 ;-1;逻辑操作符PrintHex 0FFFFFFFFh and 0FFFF0000h ;FFFF0000;高低分离符PrintHex high 11223344h ;00000033PrintHex highword 11223344h ;00001122;移位运算符PrintHex 12345678h shl 4 ;23456780ret
end start
子过程(函数)的传参与调用
;局部变量定义与过程函数调用
.code
proc1 procPrintDec 1ret
proc1 endpproc2 procPrintDec 2ret ;过程返回,如果不写这个的话,会继续执行下面语句
proc2 endpmain proc;局部变量中的类型不能使用缩写LOCAL v1: dword,v2: dword;数组LOCAL v3[3]: dwordPrintDec v1mov eax, v3[0]PrintDec eaxcall proc2 ;调用过程proc2call proc1ret
main endp
end main
;输出结果 0 0 2 1
;求和函数传参与调用
;sum proto :dword, :dword, :dword ;函数声明的主要是参数类型, 一般省略参数名
.code
sum proc v1:dword, v2:dword, v3:dwordmov eax, v1add eax, v2add eax, v3ret
sum endpmain procinvoke sum, 11, 22, 33 ;invoke是调用函数的伪指令。调用函数sum并传参。PrintDec eax ;66ret
main endp
end main
获取数组长度和字节数等
.data?v1 dw 10 dup(0) v1size=$-v1 ;获取变量v1占的字节数v1len=($-v1)/2 ;获取变量v1长度vaddr=$ ;$用于获取当前语句的地址。在.data中,只有v1,v2这种变量会产生字节开销v2 dw 11,22,33,44v2Size = $ - v2.code
main proc;获取类型占几个字节,对于数组是获取每个元素占几个字节PrintDec (type v1) ;2;测试$的作用PrintDec v1size ;20PrintDec v1len ;10;可以得出v1size到v2之间的语句的$都等于v2地址PrintDec vaddr ;4206796mov eax,offset v2PrintDec eax ;4206796;获取数组元素个数以及总字节数PrintDec (lengthof v1) ;10PrintDec (sizeof v1) ;20
main endp
end main
数据对齐
.datav1 db 0align 4;让下一个变量的起始地址保证是4的倍数;even表示偶对齐,等价于align 2;org 100表示跨越100个字节存储下一个变量v2 db 0v3 db 0
.code
main procPrintDec offset v1 ;4206592PrintDec offset v2 ;4206596 PrintDec offset v3 ;4206597ret
main endp
end main
获取变量地址以及伪指令this的使用
OFFSET和ADDR的异同:
1、offset不能获取局部变量的地址;
2、addr只能用于调用函数(invoke)中, 不能用于赋值操作;
3、addr面对局部变量时会转换为lea等指令, addr面对全局变量时则直接调用offset;
例如:lea ebx,dwVal等价于mov ebx, offset dwVal。Lea是专门获取地址的指令
4、在invoke中应尽量使用addr, 其他只用offset.
;this伪指令的使用
.dataTextAddr equ this byte ;伪指令this可让当前变量和下一个变量同址 szText db 'Asm', 0
.code
main procPrintHex offset szText ;00403000PrintHex offset TextAddr ;00403000PrintString szText ;Asmmov [TextAddr], 'a' ;给TextAddr所在地址单元赋值PrintString szText ;asmret
main endp
end main
loop的使用
;数组求和
.datadwArr dd 1,2,3,4,5
.code
main proclea edi, dwArr mov ecx, lengthof dwArr xor eax, eax
L1:add eax, [edi] add edi, type dwArr ;获取下一个元素的地址loop L1PrintDec eax ;15ret
main endp
end main
;复制字符串
.dataszSource db 'Hello World!', 0 szDest db sizeof szSource dup(0)
.code
main procmov esi, 0 mov ecx, sizeof szSource
L1:mov al, szSource[esi] mov szDest[esi], al add esi, type szSource ;调整索引loop L1;也可以使用API完成字符串复制:invoke szCopy, addr szSource, addr szDestPrintString szDest ret
main endp
end main
堆栈以及相关指令
- 程序把内存划分区域
- 全局数据区
- 全局变量在堆里
- 堆中数据由上向下排列,内存增大方向
- 局部数据区
- 局部变量,局部常量,子程序参数在栈里
- 栈中数据由下向上排列,内存减小方向
- 其它
- 全局数据区
- 栈顶指针ESP
- Win32的PUSH只可以压入32位(默认)或16位的数据,因此ESP只能±2或者±4
- push的应用
函数调用(invoke)的本质
- 本质是从右往左依次push参数,最后call函数,然后pop出栈(因为push和pop必须成对出现)
保护数据
- 调用函数前最需要保护的是EIP,因为它保存着函数调用结束后下一条指令的地址
1 执行call指令,CPU把返回地址(EIP)压入堆栈(4个字节) 2 esp在程序执行中随时可能用到,不可能使用它存取局部变量。ebp也是以堆栈段作为默认数据段的。所以先push ebp,再mov ebp, esp 3 正常操作 4 先mov esp,bsp,再pop ebp(leave指令可以起到这两个作用) 5 执行ret指令,CPU将返回地址(EIP)出栈
;交换变量值
.dataval1 dd 111val2 dd 999
;方案一:使用堆栈
.code
main procpush val1push val2pop val1pop val2PrintDec val1 ;999PrintDec val2 ;111ret
main endp
end main
;方案二:使用XCHG指令
.code
main procmov eax, val1xchg eax, val2 ;eax存储val2的值,val2存储val1的值mov val1, eaxPrintDec val1 ;999PrintDec val2 ;111ret
main endp
end main
;翻转字符串
.dataszText db 'Hello World!', 0.code
main proc;压栈mov ecx, sizeof szText - 1 xor esi, esi
@@: movzx eax, szText[esi] ;懒得给标号取名,可以使用@@,@B表示前面最近的一个标号、@F表示后面最近的一个标号 push eaxinc esiloop @B;出栈mov ecx, sizeof szText - 1xor esi, esi
@@: pop eaxmov szText[esi], alinc esiloop @BPrintString szText ;!dlroW olleHret
main endp
end main
二进制相关函数
;学习查看二进制是为了看到EFLAGS寄存器中的二进制位的变化
.dataszBin db 8 dup(?), 0
.code
main proclahf ;lahf指令是把EFLAGS寄存器的低8位字节读入ahinvoke byt2bin_ex, ah, addr szBin ;从byte数字转为二进制字符串PrintString szBin ;01000110ret
main endp
end main
标志寄存器
;置位 stc
stc ;CF=1
;复位 clc
clc ;CF=0
;取反 cmc
cmc ;CF=not CF
;如果要观察整个EFLAGS的32位, 可用PUSHFD和POPFD指令让EFLAGS进栈、出栈
数据传送指令
//以下指令均不影响标志寄存器EFlags
;mov 数值传送
;lea 地址传送
;xchg 交换指令
;xlat 换码指令
.dataszText db 'ABCDEFG', 0
.code
main proclea ebx, szText ;先将源地址放入ebxmov al, 1 ;将要访问的字节序号放入alxlat ;xlat无参数,操作和ebx、al相关PrintHex al ;42,可以看出指定字节被读入到alret
main endp
end main
;movzx 零扩展传送
;movsx 符号扩展传送
MOVZX 和 MOVSX 的区别是:
1、MOVZX会将目标寄存器中高出的位补0
2、如果源操作数的最高位是1, MOVSX会将目标寄存器中高出的位补1; 反之补0
.databVal db 90hdwVal1 dw 7FFFhdwVal2 dw 8000h
.code
main procmovzx eax, dwVal1movsx edx, dwVal1PrintHex eax ;00007FFFPrintHex edx ;00007FFFmovzx eax, dwVal2movsx edx, dwVal2PrintHex eax ;00008000PrintHex edx ;FFFF8000mov cl, bValmovzx ax, clmovsx dx, clPrintHex ax ;0090PrintHex dx ;FF90ret
main endp
end main
逻辑运算指令
;and 逻辑与,or 逻辑或,xor 逻辑异或
指令会影响EFlags,置CF=OF=0,结果影响SF、ZF、PF
可以使用xor或者not用于加密与解密字符串
;not 逻辑取反
指令不影响EFlags
;test 测试逻辑与
指令会影响EFlags,置CF=OF=0,结果影响SF、ZF、PF
test同and,但它不修改运算数,只改变标志寄存器。即它只尝试and的结果
常用于影响ZF(当test结果为0时,ZF=1),test其后往往跟着条件转移指令
【举个栗子春暖花开】
;判断字符串中每个字符的二进制位的最后一位是1还是0,统计为0为1个数
.dataszText db 'Delphi', 0
.code
main proc;清空两个寄存器用于计数xor eax, eax ;存储末位为1字符个数xor edx, edx ;存储末位为0字符个数lea esi, szText mov ecx, lengthof szText - 1
L1: test byte ptr [esi], 00000001b ;循环测试每个字符的最后一位是1还是0jz L2 ;如果是0则跳转到L2,edx+1inc eax ;反之给eax+1jmp L3
L2: inc edx
L3: inc esiloop L1PrintDec eax ;2 PrintDec edx ;4 ret
main endp
end main
位测试与位扫描指令
;位测试指令 结果影响CF
BT:位测试 Bit Test
BTS:位测试并置位 Bit Test and Set
BTR:位测试并复位 Bit Test and Reset
BTC:位测试并取反 Bit Test and Complement
【举个栗子春暖花开】
;BT把10000001的第7位复制到CF,可以看出是1
mov dx,10000001b
bt dx,7
lahf
PrintHex ah ;47,即01000111b(CF=1)
;BTS:BT+置1,BTR:BT+置0,BTC:BT+取反
;位扫描指令 结果影响ZF
BSF:位扫描,由低->高
BSR:位扫描,由高->低
1 扫描的是参数二,找到是1的位后,把位置数给参数一,并置ZF=0
2 找不到是1的位,参数一的值不变,置ZF=1
【举个栗子春暖花开】
mov dx, 0000111100001100b
bsf cx, dx
PrintDec cx ;2,即从右往左数第2位
移位指令
;移位指令 结果影响OF、SF、ZF、PF、CF
SHL、SHR:逻辑左移、逻辑右移
SAL、SAR:算数左移、算数右移
SHL和SAL:左移,低位补0,高位进CF
SHR:右移,低位进CF,高位补0
SAR:右移,低位进CF,高位不变
【举个栗子春暖花开】
mov al, 11100111b
sar al, 2 ;3表示右移两位
PrintHex al ;F9,即11111001b
;循环移位指令 结果影响OF、CF
ROL:循环左移,高位到低位并送CF
ROR:循环右移, 低位到高位并送CF
RCL:循环左移, 进位值(原CF)到低位, 高位进位到CF
RCR:循环右移, 进位值(原CF)到高位, 低位进位到CF
【举个栗子春暖花开】
clc ;CF=0
mov al, 11101011b
rcr al, 2 ;循环右移一位,al=01110101,CF=1;再右移一位,al=10111010,CF=1
PrintHex al ;BA - 10111010b
;双精度移位 结果影响OF、SF、ZF、PF、CF
三个操作数:操作数一是目的操作数,操作数二一直不变且须是寄存器,操作数三是移位数目
SHLD:双精度左移,左边被移出的位由操作数二相同数目的高位填充
SHRD:双精度右移,右边被移出的位由操作数二相同数目的低位填充
【举个栗子春暖花开】
.code
main proc;SHLDmov ax, 1100110011110000bmov dx, 1111111100000000bshld ax, dx, 2PrintHex ax ;33C3 - 0011001111000011b;SHRDmov ax, 0000111100110011bmov dx, 0000000011111111bshrd ax, dx, 2PrintHex ax ;C3CC - 1100001111001100bret
main endp
end main
符号扩展指令
CBW:将AL扩展为AX,等价于movsx ax, al
CWDE:将AX扩展为EAX,等价于movsx eax, ax
CBW和CWDE对EFLAGS无影响
movsx的特征:如果源操作数的最高位是1, movsx会将目标寄存器中高出的位补1; 反之补0
符号扩展指令的本质:一个正数(无符号)或负数(有符号)在扩展储存空间时, 使用这些指令可保证原值不变
【举个栗子春暖花开】
.code
main procmov al, 68cbwPrintHex ax ;0044PrintDec ax ;68mov al, -68cbwPrintHex ax ;FFBC,BC为-68的补码PrintDec ax ;-68ret
main endp
end main
加减指令
inc,dec,neg(求补或者求反),add,adc,sub,sbb,cmp 结果影响OF、SF、ZF、AF、PF、CF
【辨析NEG与NOT】
;neg就相当于取反(not)+1
mov val,44
not val
inc val
等价于
mov val,44
neg val
【举个栗子春暖花开】
cmp隐含执行sub,但并不改写操作数,只是影响标志位ZF和SF
.code
main procmov eax, 3cmp eax, 3lahfPrintHex ah ;46,即01000110b(ZF=1 说明两个数相等)mov eax, 3cmp eax, 2lahfPrintHex ah ;02,即00000010b(SF=0、ZF=0 说明前者>后者)mov eax, 3cmp eax, 4lahfPrintHex ah ;76,即10010111b(SF=1、ZF=0 说明前者<后者) ret
main endp
end main
乘除指令
【只有一个参数】
格式:[mul 参数] 无符号乘 影响OF、CF
如果参数是8位,则将al做乘数,结果放在ax
如果参数是16位,则将ax做乘数,结果放在dx:ax中
如果参数是32位,则将eax做乘数,结果放在edx:eax中
【只有一个参数】
格式:[imul 参数] 有符号乘 影响OF、CF
如果参数是8位,则将al做乘数,结果放在ax
如果参数是16位,则将ax做乘数,结果放在dx:ax中
如果参数是32位,则将eax做乘数,结果放在edx:eax中
【有符号乘和无符号乘结果的一致性】
如果操作数(比如7Fh和7Fh)都没有符号位, 结果一致
如果操作数的其中之一(比如7Fh和80h)有符号位, 结果不一致
如果操作数(比如80h和80h)都有符号位, 结果也一致
【有多个参数】
imul r16/r32, r16/r32/m16/m32/i ;双操作数, (1)*(2) -> (1)
imul r16/r32, r16/r32/m16/m32, i ;三操作数, (2)*(3) -> (1)
其中常数 i 的位数可以 <= 但不能 > 其他操作数
【举个栗子春暖花开】
.dataval dd 8
.code
main proc;IMUL 两个操作数mov eax, 7imul eax, valPrintDec eax ;56;IMUL 三个操作数imul eax, val, 9PrintDec eax ;72ret
main endp
end main
【只有一个参数】
格式:[div/idiv 参数] 无符号除、有符号除 对EFLAGS无影响
如果参数是8位, 将把 AX做被除数;商->AL,余数->AH
如果参数是16位, 将把DX:AX做被除数;商->AX,余数->DX
如果参数是32位, 将把EDX:EAX做被除数;商->EAX,余数->EDX
【有符号除和无符号除结果的一致性】
与乘法相同
跳转指令
- 无条件跳转:jmp
- 根据cx,ecx寄存器的值跳转:jcxz(cx=0则跳转),jecxz(ecx为0则跳转)
- 根据EFLAGS标志位跳转:je,jne,jz等等
请参考汇编语言 王爽
串指令
- 什么是"串"?
- 不单指字符串,包括所有连续的数据(比如,数组)。
- 串指令只用于内存操作
;移动字符串:从esi到edi,执行后根据df的值,esi和edi同方向变化
.dataszSource db 'Delphi 2010', 0 len equ $ - szSource - 1 ;计算szSource字符串长度szDest db len dup(?), 0
.code
main proclea esi, szSourcelea edi, szDestmov ecx, lencld ;设置df=0,以让串地址由低到高rep movsb PrintString szDest ;Delphi 2010ret
main endp
end main
;比较数组相不相等:比较esi和edi,执行后根据df的值,esi和edi同方向变化
.datadwArr1 dw 1,2,3,4,5dwArr2 dw 1,2,3,4,5,6
.code
main proclea esi, dwArr1lea edi, dwArr2mov ecx, lengthof dwArr1cmp ecx, lengthof dwArr2jne L1cldrepe cmpswjne L1PrintText '两数组相等'jmp L2
L1: PrintText '两数组不等'
L2: ret
main endp
end main
;扫描某数据是否存在:依据al/ax/eax中的数据扫描edi指向的数据,执行后根据df的值,edi变化
.dataszText db 'ABCDEFGH', 0
.code
main proclea edi, szTextmov al, 'F'mov ecx, lengthof szText - 1cldrepne scasbje L1PrintText '没找到'jmp L2
L1: sub ecx, lengthof szText - 1neg ecxPrintDec ecx ;如果找得到, 这里显示是第几个字符; 本例结果是 6
L2: ret
main endp
end main
;储存数据:将al/ax/eax中的数据储存到edi指向的数据,执行后根据df的值,edi变化
.datalen = 31szText db len dup(0), 0
.code
main proclea edi, szTextmov al, 'x'mov ecx, lencldrep stosbPrintString szText ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxret
main endp
end main
;载入数据之数组求和:将esi指向的数据载入到al/ax/eax中,执行后根据df的值,edi变化
.datadwArr dw 1,2,3,4,5,6,7,8,9,10
.code
main proclea esi, dwArrmov ecx, lengthof dwArrxor edx, edxxor eax, eaxcld
@@: lodswadd edx, eaxloop @BPrintDec edx ;55ret
main endp
end main
条件及循环伪指令
;和C语言类似
--------------
.if 条件//语句
.elseif//语句
.else//语句
.endif
--------------
.while 条件//语句
.endw
--------------
.repeat//语句
.until 条件
--------------
【举个栗子春暖花开】
.code
main procmov eax, 9.while TRUEPrintDec eaxdec eax.break .if eax == 5.endw ret
main endp
end main
【举个栗子春暖花开】
.code
main procmov eax, 0.repeatinc eax.continue .if eax == 2PrintDec eax.until eax > 3ret
main endp
end main
结构体
;结构体的使用
MyPoint structX dd ?Y dd ?
MyPoint ends.datapt1 MyPoint <11,22>
.code
main proclea ebx, pt1PrintDec (MyPoint ptr [ebx]).X ;11PrintDec (MyPoint ptr [ebx]).Y ;22ret
main endp
end main
;使用SYSTEMTIME结构获取系统时间
.datasysTime SYSTEMTIME <>
.code
main proc;SYSTEMTIME结构定义在windows.inc,GetLocalTime函数声明在kernel32.incinvoke GetLocalTime, addr sysTimePrintDec sysTime.wYear ;2021PrintDec sysTime.wMonth ;2PrintDec sysTime.wDay ;8ret
main endp
end main
【Win32汇编】学习Win32汇编相关推荐
- Win32汇编学习——windows汇编语法(小甲鱼教程)
Win32汇编学习--windows汇编语法(小甲鱼教程) 1)指令集 .386 语句是汇编语句的伪指令,类似指令有:.8086 . .186 ..286 ..386/.386p . .486/ ...
- 汇编学习笔记——汇编指令
目录 汇编指令 nop指令 mov.add.sub指令 adc.sbb指令 and.or指令 移位指令 逻辑左/右移指令 循环左/右移指令 算术左/右移指令 带进位循环左/右移指令 inc指令 pus ...
- 汇编学习笔记——伪指令
目录 伪指令 段定义 结束标记 段关联标记 数据定义 标号 offset指令 seg指令 地址标号 数据标号 代码分段 程序标识 多文件系统 字符输入 重复定义 注释 重复汇编伪指令 伪指令汇总 伪指 ...
- 汇编学习(1)——基础知识
汇编学习(1)--基础知识 ---谨以此系列文章记录我的汇编学习. 关于汇编 说起汇编语言,那自然不得不想到机器语言,在汇编语言尚未诞生之际,程序猿们只能非常苦逼的敲着0和1,还要记住一大堆复杂难记 ...
- 8086汇编学习小记-王爽汇编语言实验12
8086汇编学习小记-王爽汇编语言实验12 0号中断处理程序,开始安装在0000:0200处的程序最后用死循环导致显示不出'divided error',改成直接退出就正常显示了.注意修改ss,sp之 ...
- 寄存器---汇编学习笔记
第二章 寄存器 2.0 寄存器的绪论 一个典型的CPU由运算器.控制器.寄存器(CPU工作原理)等器件构成.内部总线实现 CPU 内部各个器件之间的联系,外部总线实现CPU和主板其他器件的联系. 在C ...
- 【汇编】汇编学习入门-系列更新20180705
版权 写在前面 小学期"硬件综合训练"需要用到"汇编",博主是在大二上学期学习的这门课,算下来半年没接触了,乘着这几天空闲梳理一下,一来找找当时学汇编的感觉以更 ...
- 8086汇编学习小记-1
8086汇编学习小记-1 View Code assume cs : codesg, ds : datasg, ss : stacksgdatasg SEGMENT... datasg ENDSsta ...
- 8086汇编学习之[BX],CX寄存器与loop指令,ES寄存器等
同类学习笔记总结: (一).8086汇编学习之基础知识.通用寄存器.CS/IP寄存器与Debug的使用 (二).8086汇编学习之DS寄存器.SS/SP寄存器 一.汇编程序的基本格式: 1.基本格式与 ...
最新文章
- 最简单的Evernote,最专业的活用方法 by 电脑玩物站长
- numpy meshgrid 和 mgrid 的两个简单实例和解析
- 查看java返回的值,JavaScript 遍历对象查找指定的值并返回路径
- POJ2299 树状数组求逆序对
- Visual studio(VS)如何修改显示字体类型和字体大小?
- Bootstrap初学(一)
- CRM呼叫中心里的Java stack
- 性冷淡风的麻将,获红点奖!网友:没有烟火气了
- 微软 Edge 浏览器将推出 iOS 和 Android 版
- 锤子濒危、金立倒闭,华米 OV 们如何艰难求生?
- 备忘--简单比较SPSS、RapidMiner、KNIME以及Kettle四款数据分析工具
- 点击按钮弹出Outlook(新建邮件状态)
- 六种Web身份验证方法比较和Flask示例代码
- 学习编程需要了解什么基础知识
- android 该文件包与具有同一名称的现有文件包存在冲突
- Android实现涂鸦功能
- 离焦、球差、像散等成像结果
- 看完李宏毅的视频我决定学好英语了
- 【课程设计】8086汇编实现打字小游戏
- 广东指导晚造水稻工作 国稻种芯·中国水稻节:惠州加强防治
热门文章
- Docker复习08——Docker-compose容器编排
- 关于qt执行带有中文参数的DOS命令执行不成功
- 深度学习论文翻译解析Densely Connected Convolutional Networks
- MySQL备份Percona Xtrabackup安装和卸载
- js canvas 五指棋,138行实现五指棋
- [小窍门] Idea编辑器光标样式修改
- 【clickhouse】Centos7部署Clickhouse数据库
- 游戏扫码登录多功能工具箱集合微信小程序源码
- error pulling image configuration: download failed after attempts=6: dialing production.cloudflare.d
- 如何利用 Kyligence+tableau提高分析效率?