学习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汇编相关推荐

  1. Win32汇编学习——windows汇编语法(小甲鱼教程)

    Win32汇编学习--windows汇编语法(小甲鱼教程) 1)指令集 .386 语句是汇编语句的伪指令,类似指令有:.8086 . .186  ..286  ..386/.386p  . .486/ ...

  2. 汇编学习笔记——汇编指令

    目录 汇编指令 nop指令 mov.add.sub指令 adc.sbb指令 and.or指令 移位指令 逻辑左/右移指令 循环左/右移指令 算术左/右移指令 带进位循环左/右移指令 inc指令 pus ...

  3. 汇编学习笔记——伪指令

    目录 伪指令 段定义 结束标记 段关联标记 数据定义 标号 offset指令 seg指令 地址标号 数据标号 代码分段 程序标识 多文件系统 字符输入 重复定义 注释 重复汇编伪指令 伪指令汇总 伪指 ...

  4. 汇编学习(1)——基础知识

    汇编学习(1)--基础知识 ---谨以此系列文章记录我的汇编学习.  关于汇编 说起汇编语言,那自然不得不想到机器语言,在汇编语言尚未诞生之际,程序猿们只能非常苦逼的敲着0和1,还要记住一大堆复杂难记 ...

  5. 8086汇编学习小记-王爽汇编语言实验12

    8086汇编学习小记-王爽汇编语言实验12 0号中断处理程序,开始安装在0000:0200处的程序最后用死循环导致显示不出'divided error',改成直接退出就正常显示了.注意修改ss,sp之 ...

  6. 寄存器---汇编学习笔记

    第二章 寄存器 2.0 寄存器的绪论 一个典型的CPU由运算器.控制器.寄存器(CPU工作原理)等器件构成.内部总线实现 CPU 内部各个器件之间的联系,外部总线实现CPU和主板其他器件的联系. 在C ...

  7. 【汇编】汇编学习入门-系列更新20180705

    版权 写在前面 小学期"硬件综合训练"需要用到"汇编",博主是在大二上学期学习的这门课,算下来半年没接触了,乘着这几天空闲梳理一下,一来找找当时学汇编的感觉以更 ...

  8. 8086汇编学习小记-1

    8086汇编学习小记-1 View Code assume cs : codesg, ds : datasg, ss : stacksgdatasg SEGMENT... datasg ENDSsta ...

  9. 8086汇编学习之[BX],CX寄存器与loop指令,ES寄存器等

    同类学习笔记总结: (一).8086汇编学习之基础知识.通用寄存器.CS/IP寄存器与Debug的使用 (二).8086汇编学习之DS寄存器.SS/SP寄存器 一.汇编程序的基本格式: 1.基本格式与 ...

最新文章

  1. 最简单的Evernote,最专业的活用方法 by 电脑玩物站长
  2. numpy meshgrid 和 mgrid 的两个简单实例和解析
  3. 查看java返回的值,JavaScript 遍历对象查找指定的值并返回路径
  4. POJ2299 树状数组求逆序对
  5. Visual studio(VS)如何修改显示字体类型和字体大小?
  6. Bootstrap初学(一)
  7. CRM呼叫中心里的Java stack
  8. 性冷淡风的麻将,获红点奖!网友:没有烟火气了
  9. 微软 Edge 浏览器将推出 iOS 和 Android 版
  10. 锤子濒危、金立倒闭,华米 OV 们如何艰难求生?
  11. 备忘--简单比较SPSS、RapidMiner、KNIME以及Kettle四款数据分析工具
  12. 点击按钮弹出Outlook(新建邮件状态)
  13. 六种Web身份验证方法比较和Flask示例代码
  14. 学习编程需要了解什么基础知识
  15. android 该文件包与具有同一名称的现有文件包存在冲突
  16. Android实现涂鸦功能
  17. 离焦、球差、像散等成像结果
  18. 看完李宏毅的视频我决定学好英语了
  19. 【课程设计】8086汇编实现打字小游戏
  20. 广东指导晚造水稻工作 国稻种芯·中国水稻节:惠州加强防治

热门文章

  1. Docker复习08——Docker-compose容器编排
  2. 关于qt执行带有中文参数的DOS命令执行不成功
  3. 深度学习论文翻译解析Densely Connected Convolutional Networks
  4. MySQL备份Percona Xtrabackup安装和卸载
  5. js canvas 五指棋,138行实现五指棋
  6. [小窍门] Idea编辑器光标样式修改
  7. 【clickhouse】Centos7部署Clickhouse数据库
  8. 游戏扫码登录多功能工具箱集合微信小程序源码
  9. error pulling image configuration: download failed after attempts=6: dialing production.cloudflare.d
  10. 如何利用 Kyligence+tableau提高分析效率?