• 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
      
  • 相关阅读:
    hausaufgabe--python 37 -- self in Class
    hausaufgabe--python 36-- Basic knowledge of Class
    hausaufgabe--python 35
    hausaufgabe--python 34
    hausaufgabe--python 33
    Retrofit2的使用简单介绍
    android中的Application作用
    第三章 Android控件架构与自定义控件详解
    第一章 Android体系与系统架构
    写在前面的话
  • 原文地址:https://www.cnblogs.com/beyondzones/p/15011475.html
Copyright © 2020-2023  润新知