32位汇编知识总结

重要知识

  • 汇编读写
;WriteString	 ReadString

;WriteString
; Writes a null-terminated string to standard
; output. Input parameter: EDX points to the string.
;ReadString 
; Reads a string of up to 128 characters from the console
; past the end of line, and places the characters in a buffer.
; Strips off CR/LF from the input buffer.
; Receives: EDX points to the input buffer,
;           ECX contains the maximum string length
; Returns:  EAX = size of the input string.

;WriteInt	 ReadInt

;WriteInt 
;Receives: EAX = the integer 输出eax
;ReadInt
;Returns:  If CF=0, the integer is valid, and EAX = binary value.
;If CF=1, the integer is invalid and EAX = 0.


;WriteHex  	 ReadHex

;WriteHex
; Writes an unsigned 32-bit hexadecimal number to standard output.
; Input parameters: EAX = the number to write.
;ReadHex 
;Reads a 32-bit hexadecimal integer from standard input
;Returns: EAX = binary integer value

;Crlf
; Writes a carriage return / linefeed(写入回车或换行符)


;WriteChar
; Write a character to standard output
; Recevies: AL = character

  • 变量的分类(汇编中用大小区分变量)

;DB / byte 定义字节. 8位(一个字节数据占一个字节单元,读完一个,偏移量加1)
;DW / word 定义Word.通常在x86 32位系统上为2个字节(一个字节数据占2个字节单元,读完一个,偏移量加2)
;DD / Dword 定义双字.典型的x86 32位系统通常为4个字节(一个双字节数据占4个字节单元,读完一个,偏移量加4)
  • 跳转指令
; jmp :无条件转移指令

; jnc :表示不进位时跳转
; jnz :表示非0跳转

;有符号数比较
; jg :greater than
; jz :zero equal to
; jl :less than

;无符号比较
;ja :above var1>var2
;jz,je     var1=var2
;jb :below var1<var2

;xchg 交换两个变量的值
;交换指令XCHG是两个寄存器,寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同,可以是一个字节,也可以是一个字,也可以是双字
  • 操作数与四则运算
opcode oprand1 [,operand2]
;1.oprand1称为目的操作数
;  oprand2称为原操作数 
;2.目的操作数不能为常数
;3.两个操作数的类型必须一样(大小相同)
;4.指令如果涉及到两个操作数,两个操作数不能都是内存变量,必须有一个是寄存器

;四则运算
add oprand1,operand2 eflag;无进位
addc oprand1,operand2 CF;有进位
add byte ptr [m1],20;将m1当作byte长度看待
add word ptr [m1],20;将m1当作word长度看待
add dword ptr [m1],20;将m1当作dword长度看待

sub oprand1,oprand2 eflag

mul oprand1 ;结果必须由64位保存,结果储存在edx,eax中(高位在edx中,低位在eax中)
;字节操作数 (AX)
;字操作数 (DX,AX)
;双字操作数 (EDX,EAX)
;mul通过操作数来辨别乘法进行的位数(如果是立即数无法辨别大小)


imul oprand1 ;有进位,存在edx,eax
;被乘数和积在edx,eax组成的64位中

div  oprand ;被除数在edx,eax组成的64位中
;结果:商在eax中,余数在edx中(如果被除数是32位记得将edx赋值为0)


  • 函数实现
F1 PROC
	ret
F1 ENDP

;规定函数返回值放在寄存器内

;函数内用栈保存寄存器信息
isPrime PROC
	push ebx
	push edx
	push esp
	
	
	pop esp
	pop edx
	pop ebx
	ret
isPrime ENDP

;习惯规定如果返回值32位放的下的话默认放在eax中
  • 寄存器的使用
;32位寄存器高16位无法直接使用,对应的低16位AX,BX,CX,DX,SI,DI,BP,SP可视情况使用
;以上16位寄存器还可以细分:
;AX:AH AL
;BX:BH BL
;CX:CH CL
;DX:DH DL


;EAX是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

;EBX是"基地址"(base)寄存器, 在内存寻址时存放基地址。

;ECX是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

;EDX则总是被用来放整数除法产生的余数。

;ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串

;EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 

;ESP专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节

;EIP储存下一条cpu执行的指令地址



;EFLAG取值含义
;IP: EI/DI 中断标志位
;中断控制在硬件中完成(接口和CPU中的中断控制指令集)
  • X进制常数表示
;进制前缀:
;二进制 0B		0B101010
;八进制 0O	 	0O767676
;十六进制 0x		0xA7B2

;进制后缀:
;二进制 B
;八进制 O
;十进制 D
;十六进制 H
  • 寻址方式
;立即寻址(目的操作数是常量)
;直接寻址(数据在变量内 eg. val)
;寄存器寻址(数据在寄存器内)
;寄存器间接寻址 (不能出现[100],应该用变量定义,再使用变量名;寻址寄存器用32位) 
mov eax,offset val
mov ebx,[eax]
;寄存器相对寻址(在寄存器间接寻址的基础上对地址加减偏移量)
;基址—变址寻址
;基址—变址相对寻址
  • 指令
;逻辑运算指令

;逻辑非指令 NOT OPR

;逻辑与指令 AND DST,SRC

;逻辑或指令 OR DST,SRC

;异或指令 XOR DST,SRC

;测试指令 TEST OPR1,OPR2
;移位指令

;逻辑左移 SHL OPR,CNT   (SHL = Shift Left)
;逻辑右移 SHR OPR,CNT   (SHR = Shift Right)

;CNT(存在CL 八位寄存器中)   
;串处理指令
;B:BYTE  W:WORD  D:DOUBLE WORD
;MOVS(MOVSB,MOVSW,MOVSD)
;源串地址放在ESI中,源串长度放在ECX中(以单位偏移量为单位长度),目的串地址放在EDI中
;DF标志位 DF=0时表示ESI/EDI储存串的首地址,DF=1时表示ESI/EDI储存串的尾地址

;STOS  初始化串
;指令对应寄存器(存放初始化单元)
;STOSB  AL
;STOSW  AX
;STOSD  EAX

;LODS	从串地址中取出一个子节/字/双字放在AL/AX/EAX中
;CMPS	比较两个串的大小(较小串长度放在ECX中)
;SCAS	扫描字符串,在字符串中找与AL/AX/EAX中数据相同或不同的子串(比较最大次数放在ECX中)
 

;设置方向标志位  CTD STD
;CLD指令功能:(STD功能相反)
;将标志寄存器Flag的方向标志位DF清零。
;在字串操作中使变址寄存器SI或DI的地址指针自动增加,字串处理由前往后。

;串重复前缀
;REP REPE/REPZ REPNE/REPNZ
;堆栈操作

;进栈指令
;push pushad
;pop popad
;pushad/popad 可以将寄存器在一行内一次性入栈/出栈
;PUSHAD指令压入32位寄存器,其入栈顺序是:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI(执行后ESP- 32)
;POPAD指令按照与上面相反的顺序依次弹出寄存器的值,顺序为EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX(执行后ESP+32)

ret
;ret指令的内部操作是:栈顶字单元出栈,其值赋给IP寄存器。即实现了一个程序的转移,将栈顶字单元保存的偏移地址作为下一条指令的偏移地址。

;函数执行完时  ret 12
;栈顶pop 赋值给EIP  ESP地址加12


  • 小知识点
;分号之后的部分为注释

call DumpRegs ;显示寄存器信息D

;伪指令有2个特点:
;(1)由于是伪“指令”,因而它只存在于汇编语言中。高级语言中不叫指令,叫语句;
;(2)由于是“伪”指令,也即“假”指令,因而不是可执行指令,不会产生机器代码,不会占用ROM空间,只用于汇编过程中为汇编程序提供汇编信息。

mov ebx,var1
cmp ebx,var2 ;var1-var2=>eflag 相减后会改变eflag,执行该语句后var1,var2不变

;负数用的是补码表示方式

;小端编址方式: 00404000 -> 18 FC FF FF
     
;数组用法: 
;arr dd 10 DUP(?)
;arr dd 1,2,34,3,5,6,8 直接为数组赋值
;arrlen = ($-arr) / 4 可以用这种方式动态获得数组大小(注意必须紧连着arr的定义,4代表的是偏移量)
;一个内存地址对应一个字节(Byte): 0xFF 或者说 8-bit:11110000b。

;Excellent db 'Excellent',0 ;''中的字符串不含结束字符0,需要手动添加

lea edx,msg ;==mov edx,offset msg
;lea = load effective address 

inc eax ;自增
dec eax ;自减
;操作数可以是变量,不影响CF标志
again:
	add v,1 ;inc v 使用inc不会导致eflag改变,inc不会造成进位
	jnc again ;jnc 表示不进位时跳转

;相同的mov指令但是选用的寄存器不同机器码也可能不一样

;外设相对于cpu可以看作寄存器

;带符号扩展
;MOVSX reg1, reg2
;MOVSX reg, mem
;如果拓展不用用到高位,高位自动清零
;目的操作数的位数要比源操作数大
;源操作数可以是8位或者16位,而目的操作数必须是16位或者32位

;循环
mov ecx,n ;n为常数
Addr:
	;循环体
	loop Addr ;ecx-- 并判断ecx与0是否相等,如果不相等,继续循环;如果相等,跳出循环 
	

汇编程序模板

  • 模板

    TITLE Program Template ;Template.asm
    
    INCLUDE Irvine32.inc
    .data
    ;此处定义全局变量
    .code
    ;代码段
    main PROC
    
    	exit
    main ENDP
    
    F1 PROC
    
    	ret
    F1 ENDP
    
    END main
    
    ;传参模板(保护现场)
    push x
    push y
    f1 proc
    push ebp
    mov ebp,esp
    sub esp,4
    pushad
    
    popad
    mov eax,[ebp-4]
    add esp,4
    pop ebp
    ret 8
    f1 endp
    ;用栈保存寄存器状态,防止修改寄存器值影响main函数执行
    
  • 基础计算

    TITLE Add and Subtract
    INCLUDE Irvine32.inc
    .data
    val1 DWORD 10000h ; h代表16进制,10000h是十进制2^16
    val2 DWORD 40000h
    val3 DWORD 20000h
    ;finalVal DWORD
    .data? ;其中的数据段也可以定义在.data中
    finalVal DWORD ? ;定义未初始化数据
    temp DWORD 2 DUP(?) ;dup在汇编中是一条伪指令,用来重复初始化数据 此处就是将两个DWORD的空间都定为?
    .code
    main PROC
    	mov eax,val1 
    	add eax,val2
    	sub eax,val3
    	mov finalVal,eax ;将寄存器eax中保存的运算结果保存在数据段finalVal中
    	call DumpRegs ;显示寄存器信息(registers是寄存器的意思)
    	exit
    main ENDP
    END main
    
  • 整数输入输出与比较

    INCLUDE Irvine32.inc
    
    .data
    var1 dd ?
    var2 dd ? ;dd是指doubleword (4个子节)
    
    .code
    
    main PROC
    	
    	call ReadInt ;读入Interger,存入eax
    	mov var1,eax
    	
    	call ReadInt
    	mov var2,eax
    	
    	cmp var1,eax ;比较var1和eax的大小
    	jl L1		 ;跳转到L1
    	mov eax,var1
    L1:	call WriteInt ;输出eax中存放的数
    
    	exit
    main ENDP
    
    END main
    
  • 条件判断与分支

    INCLUDE Irvine32.inc
    
    .data
    mark DD ?
    Excellent db 'Excellent',0 ;''中的字符串不含结束字符0,需要手动添加
    Good db 'Good',0
    Pass db 'Pass',0
    Failed db 'Failed',0
    
    .code
    main PROC
    	call ReadInt
    	mov mark,eax
    	cmp eax,90
    	Jb L1
    	mov edx,offset Excellent
    	jmp final
    
    L1:	cmp eax,80
    	jb L2
    	mov edx,offset Good
    	jmp final
    
    L2:	cmp eax,60
    	jb L3
    	mov edx,offset Pass
    	jmp final
    
    L3:	mov edx,offset Failed
    
    final:	call WriteString ;WriteString的使用与EDX有关
    	exit
    main ENDP
    
    END main
    
    
  • 输入10个整数比较大小

    INCLUDE Irvine32.inc
    .data
    arr dd 10 dup(?)
    .code
    main PROC
    	mov ebx,0
    again1:	cmp ebx,10
    	jae final1
    	call ReadInt
    	mov [arr + 4*ebx],eax
    	add ebx,1
    	jmp again1
    	
    final1:
    	
    	mov ebx,1
    	mov eax,[arr] 
    again2:	cmp ebx,10
    	jae final2
    	cmp eax,[arr + 4*ebx]
    	jae L1
    	mov eax,[arr + 4*ebx]
    L1:	
    	add ebx,1
    	jmp again2
    	
    final2:
    	call WriteInt
    	exit
    main ENDP
    
    END main
    
  • 判断32位以内自然数是否为素数

    
    INCLUDE Irvine32.inc
    ;正整数判断是否是素数
    .data
    val1 dd ?
    val2 dd 2
    YES db 'Yes',0
    NO db 'No',0
    .code
    main PROC
    	call ReadInt 
    	cmp eax,1
    	jz result1
    	mov val1,eax
    	mov edx,0
    	div val2
    	mov ecx,eax
    	mov edx,0
    
    again:	mov edx,0
    	mov eax,val1
    	cmp ecx,1
    	jz result2
    	div ecx
    	cmp edx,0
    	jz result1
    	;sub ecx,1
    	loop again
    	  
    	
    result1: mov edx,offset	NO
    	call WriteString
    	jmp over
    result2: mov edx,offset	YES
    	call WriteString
    over:	
    	exit
    main ENDP
    
    END main
    
  • 输入整数输出不带加号整数

    INCLUDE Irvine32.inc
    .data
    val1 dd ?
    val2 dd 10
    msg db '0',0
    .code
    main PROC
            call ReadInt
            mov val1,eax
            mov ecx,0
    
    again:  mov edx,0
            mov eax,val1
            div val2
            mov val1,eax
            mov eax,edx
            add al,'0'
            push eax
            add ecx,1
            mov ebx,val1
            cmp ebx,0
            jz over
            jmp again
    
    over:
    again1: 
            pop eax
            call WriteChar
            loop again1
            
        exit
    main ENDP
    
    END main
    
  • ret使用案例

    INCLUDE Irvine32.inc
    .data
    msg1 db 'Hello world',0
    msg2 db 'Goodbye',0
    .code
    main PROC
            push next
            jmp f1
    next:   call crlf
            lea edx,msg2
            call writeString
            exit
        
    main ENDP
    
    f1 PROC
        lea edx,msg1
        call writeString
        ret
    f1 ENDP
    END main
    
    
    
  • 进制转换

    INCLUDE Irvine32.inc
    .data
    val1 dd ?
    val2 dd ?
    arr db '0123456789ABCDEF'
    .code
    main PROC
            call ReadInt
            mov val1,eax
            call ReadInt
            mov val2,eax
            call change
    
            exit
    main ENDP
    
    change PROC
            mov ecx,0
            
    again:  mov edx,0
            mov eax,val1
            div val2
            mov val1,eax
            mov al,[arr+edx]
            push eax
            add ecx,1
            mov ebx,val1
            cmp ebx,0
            jz over
            jmp again
    over:
    again1: 
            pop eax
            call WriteChar
            loop again1
            ret
    change ENDP
    
    END main
    
  • 选择排序(升序)

    INCLUDE Irvine32.inc
      .data
      arr dd 1,100,-9,-8,-100,2000,435,875,-2321,0
      arrLen = ($ - arr) / 4
      tempLen dd arrLen
      msg1 db "Before sort : ",0
      msg2 db "After sort : ",0
      .code
      main PROC
          
          mov edx,offset msg1
          call WriteString
          call crlf
      
          mov esi,0
      again1:
          cmp esi,arrLen
          jz next1
          mov eax,arr[4*esi]
          call WriteInt
          mov al,' '
          call WriteChar
          inc esi
          jmp again1
          
      next1:
          call crlf
          mov esi,1
          mov ecx,tempLen
      again2:  
          cmp esi,arrLen
          jz next2
          call findMaxIndex
          dec ecx
          ;call WriteInt
          ;call crlf
          mov ebx,[arr+4*ecx]
          mov edx,[arr+4*eax]
          mov [arr+4*ecx],edx
          mov [arr+4*eax],ebx
          ;mov eax,ecx
          ;call WriteInt
          ;call crlf
          inc esi
          jmp again2
      
      next2:
      
          mov edx,offset msg2
          call WriteString
          call crlf
          mov esi,0
      again3:
          cmp esi,arrLen
          jz next3
          mov eax,arr[4*esi]
          call WriteInt
          mov al,' '
          call WriteChar
          inc esi
          jmp again3
      
      next3:
          exit
      main ENDP
      
      findMaxIndex PROC
          push esi
          
           
          mov esi,0
          mov eax,0
      again:
          inc esi
          cmp esi,ecx
          jz over
          mov ebx,[arr+4*eax]
          cmp ebx,[arr+4*esi]
          jge next
          mov eax,esi
      next:
          jmp again
      
      over:
          
          pop esi
          ret
      findMaxIndex ENDP
      
      END main
    
  • 求最大公约数

     INCLUDE Irvine32.inc
     .data
     m dd ?
     n dd ?
     r dd ?
     msg db '最大公约数是:',0
     .code
     main PROC
         call ReadInt
         mov m,eax
         call ReadInt
         mov n,eax
    
         cmp m,eax   ;保证 m >= n  
         jge next
         xchg m,eax
         xchg n,eax  
     next:
    
         call gcd
    
         mov eax,m
         mov edx,offset msg
         call WriteString
         call WriteInt 
         exit
     main ENDP
     gcd PROC
         again:
         mov edx,0
         mov eax,m
         mov ebx,n
         div ebx
         mov m,ebx
         mov n,edx
         cmp edx,0
         jz next1
    
         jmp again
     next1:
         ret
     gcd ENDP
     END main
    
  • 求完美数

    INCLUDE Irvine32.inc
    .data
    k dd ?
    count dd 0
    .code
    main PROC
        call ReadInt
        mov k,eax
        mov esi,0
        mov ebx,2
    again:
        cmp esi,k
        jz next
        call findNum
        mov esi,count
        inc ebx
        jmp again
    next:
        exit
    main ENDP
    findNum PROC
        push eax
        push esi
        mov esi,1
        mov ecx,0
    again1:
        cmp esi,ebx
        jz over
        mov eax,ebx
        mov edx,0
        div esi
        cmp edx,0
        jnz next1
        add ecx,esi
    next1:
        inc esi
        jmp again1
    over:
        cmp ecx,ebx
        jnz next2
        mov eax,ebx
        call WriteInt
        call crlf
        inc count
    next2:
    s
        pop esi
        pop eax
        ret
    findNum ENDP
    END main
    
    
  • 正整数的素数分解

    INCLUDE Irvine32.inc
    .data
    n dd ?
    temp dd ?
    divNum dd 10
    .code
    main PROC
        call ReadInt
        mov temp,eax
        mov n,eax
        mov ecx,0
    again3:
        cmp eax,0
        jz next4
        mov edx,0
        div divNum
        push edx    
        inc ecx
        jmp again3
    next4:
    
    again4:
        cmp ecx,0
        jz next5
        pop eax
        add al,'0'
        call WriteChar
        dec ecx
        jmp again4
    
    next5:
    
        mov al,'='
        call WriteChar
        mov esi,2
    
    again:
        mov ecx,0
        call findPrime
        cmp ecx,0
        jz next2
        mov eax,esi
        add al,'0'
        call WriteChar
        mov al,'^'
        call WriteChar
        mov eax,ecx
        add al,'0'
        call Writechar
        mov eax,temp
        cmp eax,1
        jz next3 
        mov al,'*'
        call WriteChar
    next3:
    next2:
        cmp esi,n
        jz next 
        inc esi
        jmp again
    next:
        exit
    main ENDP
    
    findPrime PROC
    
    again1:
        mov edx,0
        mov eax,temp
        div esi
        cmp edx,0
        jnz next1
        inc ecx
        mov temp,eax
    
        jmp again1
    next1:
        ret
    findPrime ENDP
    
    END main
    
  • byte ptr [arr]测试

    INCLUDE Irvine32.inc
    .data
    arr1 dd 1,5,3,6,234,2,56
    arr2 db 123,4,44,111,67,34,7,88
    arr3 dw 113,3455,67,234,777,432,1,3,5
    .code
    main proc
        mov eax,dword ptr [arr1] ;使用时源操作数和目的操作数类型需要对等
        call WriteInt
        mov al,byte ptr [arr1]
        call WriteInt
        mov ax,word ptr [arr1]
        call WriteInt
        exit
    main endp
    
    end main
    
原文地址:https://www.cnblogs.com/beyondzones/p/15011475.html