美文网首页
汇编学习(4), 整数,栈,浮点

汇编学习(4), 整数,栈,浮点

作者: android小奉先 | 来源:发表于2022-12-02 20:40 被阅读0次

本篇介绍

本篇介绍汇编的整数,浮点运算,还有栈。

整数运算

代码如下:

; icalc.asm
extern printf
section .data                           
    number1 dq  128 ; the numbers to be used to                     
    number2 dq  19  ; show the arithmetic
    neg_num dq  -12 ; to show sign extension
    fmt     db  "The numbers are %ld and %ld",10,0                  
    fmtint  db  "%s %ld",10,0 
    sumi    db  "The sum is",0  
    difi    db  "The difference is",0
    inci    db  "Number 1 Incremented:",0
    deci    db  "Number 1 Decremented:",0
    sali    db  "Number 1 Shift left 2 (x4):",0
    sari    db  "Number 1 Shift right 2 (/4):",0
    sariex  db  "Number 1 Shift right 2 (/4) with "
            db  "sign extension:",0
    multi   db  "The product is",0
    divi    db  "The integer quotient is",0
    remi    db  "The modulo is",0 
section .bss
        resulti resq    1
        modulo  resq    1
section .text                           
    global main                     
main:
    push    rbp
    mov     rbp,rsp
; displaying the numbers
        mov rdi, fmt
        mov rsi, [number1]
        mov rdx, [number2]
        mov rax, 0
        call printf
; adding---------------------------------------------------------------------
    mov rax, [number1]
    add rax, [number2]      ; add number2 to rax
    mov [resulti], rax      ; move sum to result
    ; displaying the result
        mov rdi, fmtint
        mov rsi, sumi
        mov rdx, [resulti]
        mov rax, 0
        call printf
; substracting---------------------------------------------------------------
    mov rax, [number1]
    sub rax, [number2]      ; subtract number2 from rax
    mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, difi
        mov rdx, [resulti]
        mov rax, 0
        call printf
; incrementing----------------------------------------------------------------- 
    mov rax, [number1]
    inc rax         ; increment rax with 1
    mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, inci
        mov rdx, [resulti]
        mov rax, 0
        call printf
; decrementing-----------------------------------------------------------------
    mov rax, [number1]
    dec rax         ; decrement rax with 1
        mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, deci
        mov rdx, [resulti]
        mov rax, 0
        call printf
; shift arithmetic left------------------------------------------------------
    mov rax, [number1]
    sal rax, 2          ; multiply rax by 4
    mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, sali
        mov rdx, [resulti]
        mov rax, 0
        call printf
; shift arithmetic right------------------------------------------------------
    mov rax, [number1]
    sar rax, 2          ; divide rax by 4
    mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, sari
        mov rdx, [resulti]
        mov rax, 0
        call    printf
; shift arithmetic right with sign extension ---------------------------------
    mov rax, [neg_num]
    sar rax, 2          ; divide rax by 4
    mov [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, sariex
        mov rdx, [resulti]
        mov rax, 0
        call    printf
; multiply-------------------------------------------------------------------
    mov     rax, [number1]
    imul    qword [number2]     ; multiply rax with number2
    mov     [resulti], rax
    ; displaying the result
        mov rdi, fmtint
        mov rsi, multi
        mov rdx, [resulti]
        mov rax, 0
        call    printf
; divide---------------------------------------------------------------------
    mov     rax, [number1]
    mov     rdx, 0          ; rdx needs to be 0 before idiv
    idiv    qword [number2]     ; divide rax by number2, modulo in rdx
    mov     [resulti], rax
    mov     [modulo], rdx   ; rdx to modulo
    ; displaying the result
        mov rdi, fmtint
        mov rsi, divi
        mov rdx, [resulti]
        mov rax, 0
        call    printf
        mov rdi, fmtint
        mov rsi, remi
        mov rdx, [modulo]
        mov rax, 0
        call    printf      
mov rsp,rbp
pop rbp
ret

结果如下:
The numbers are 128 and 19
The sum is 147
The difference is 109
Number 1 Incremented: 129
Number 1 Decremented: 127
Number 1 Shift left 2 (x4): 512
Number 1 Shift right 2 (/4): 32
Number 1 Shift right 2 (/4) with sign extension: -3
The product is 2432
The integer quotient is 6
The modulo is 14

add,sub

可以用于有符号,也可以用于无符号,第二个操作数会加到第一个操作数上。对于有符号数,如果第一个操作数放不下结果,那么CF 标记会置位,对于无符号数,OF标记会置位,如果结果是0,ZF标记会置位,如果结果是负数,那么SF标记会置位。
sub 和add类似,无需重复。

sal,sar

算术左移,算术右移,在移动的 时候会考虑符号位,比如对于负数,在做sar的时候,就会在最高位补1。这儿会见证一次数字的神奇:

举一个例子, 比如一个8位的寄存器,需要表示 -4,那么结果如下:
0000 0100
=>
1111 1011 
+ 1
1111 1100 (-4 的补码,也就是计算机中真正的存储形式)

算术右移1位
1111 1110 (-2)
也就是高位补一个符号位,就可以正确表示除以2的结果!

imul, idiv

mul用于无符号数乘法,imul用于有符号数乘法,rax用来存放第一个参数,乘法会用到rdx,rax2个寄存器,rdx用来存放高64位,rax存放低64位。
对于除法,rax用来存放被除数,也用来存放结果的整数部分,rdx用来存放余数,因此使用idiv之前,需要将rdx清零。

先看一个代码,反转字符串:

; stack.asm
extern printf
section .data                           
    string      db  "ABCDE",0
    stringLen   equ $ - string-1        ; stringlength without 10 and 0
    fmt1        db  "The original string: %s",10,0
    fmt2        db  "The reversed string: %s",10,0
section .bss
section .text                           
    global main                     
main:
    push rbp
    mov rbp,rsp

; Print the original string
    mov     rdi, fmt1
    mov     rsi, string
    mov     rax, 0      
    call    printf      

;push the string char per char on the stack    
        xor rax, rax            
        mov rbx, string     ; address of string in rbx
        mov rcx, stringLen  ; length in rcx counter     
        mov r12, 0      ; use r12 as pointer
    pushLoop:
; push char per char on the stack
        mov al, byte [rbx+r12] ; move char into rax
        push rax            ;push rax on the stack  
        inc r12         ; increase char pointer with 1
        loop pushLoop       ; continue loop

;pop the string char per char from the stack
;this will reverse the original string 
        mov rbx, string     ; address of string in rbx
        mov rcx, stringLen  ; length in rcx counter 
        mov r12, 0      ; use r12 as pointer
    popLoop:
        pop rax         ; pop a char from the stack
        mov byte [rbx+r12], al ;move the popped char into string
        inc r12         ; increase char pointer with 1
        loop popLoop        ; continue loop
        mov byte [rbx+r12],0        ; terminate string with 0

; Print the reversed string
    mov     rdi, fmt2
    mov     rsi, string
    mov     rax, 0      
    call    printf                  

    mov rsp,rbp
    pop rbp
    ret

结果:
The original string: ABCDE
The reversed string: EDCBA

上面程序本质上就是按照栈的FILO规则,第一个loop先将字符串push到栈上,第二个loop再读出来,这样就把字符串反过来了。可以在第一个循环结束后打一个断点,显示rsp指向地址的内容

> i registers rsp
 rsp            0x7fffffffe468      0x7fffffffe468
> x /5cg 0x7fffffffe468
 0x7fffffffe468:    69 'E'  68 'D'
0x7fffffffe478: 67 'C'  66 'B'
0x7fffffffe488: 65 'A'

浮点

首先看下浮点在计算机中的表示:
32位单精度
1 个符号位,8个指数位,23个分数位
64位双精度
1个符号位,11个指数位,52个分数位

对于指数位,还有一个偏移值,对于单精度,偏移值是127,双精度偏移值是1023。接下来看一个例子:

1101010.01011 (106 + 1/4 + 1/16 + 1/32 = 106 + 11/32)

=1.0101001011 x 2^6

由于是正数,符号位是0,指数位是 6 + 127 = 133,那么表示结果就是:
0 10000101 01010010110000000000000

接下来看一点浮点的代码:

; fcalc.asm
extern printf
section .data                           
    number1 dq  9.0                 
    number2 dq  73.0
    fmt db  "The numbers are %f and %f",10,0                    
    fmtfloat    db  "%s %f",10,0 
    f_sum   db  "The float sum of %f and %f is %f",10,0
    f_dif   db  "The float difference of %f and %f is %f",10,0
    f_mul   db  "The float product of %f and %f is %f",10,0
    f_div   db  "The float division of %f by %f is %f",10,0
        f_sqrt  db  "The float squareroot of %f is %f",10,0
section .bss
section .text                           
    global main                 
main:
    push    rbp     ; necessary because of printf with float
    mov     rbp,rsp
; print the numbers
    movsd xmm0, [number1]
    movsd xmm1, [number2]
    mov rdi,fmt
    mov rax,2   ; two floats
    call    printf
; sum   
    movsd xmm2, [number1]   ; double precision float into xmm
    addsd xmm2, [number2]   ; add into to xmm
        ; print the result
        movsd xmm0, [number1]
        movsd xmm1, [number2]
        mov rdi,f_sum
        mov rax,3   ; one float
        call    printf
; difference    
    movsd xmm2, [number1]   ; double precision float into xmm
    subsd xmm2, [number2]   ; subtract from xmm
        ; print the result
        movsd xmm0, [number1]
        movsd xmm1, [number2]
                mov rdi,f_dif
        mov rax,3   ; three floats
        call    printf
; multiplication  
    movsd xmm2, [number1]   ; double precision float into xmm
    mulsd xmm2, [number2]   ; multiply with xmm 
        ; print the result
                mov rdi,f_mul
                movsd xmm0, [number1]
        movsd xmm1, [number2]
        mov rax,3   ; three floats
        call    printf
; division
    movsd xmm2, [number1]   ; double precision float into xmm
    divsd xmm2, [number2]   ; dividdatae xmm0 
        ; print the result
                mov rdi,f_div
                movsd xmm0, [number1]
        movsd xmm1, [number2]
        mov rax,1   ; one float
        call    printf
; squareroot
   sqrtsd xmm1, [number1]   ; squareroot double precision float in xmm
        ; print the result
                mov rdi,f_sqrt
                movsd xmm0, [number1]
        mov rax,2   ; one float
        call    printf
; exit
    mov rsp,rbp              
    pop rbp     ; undo the push at the beginning
    ret

        mov rdi,f_sum
        mov rax,3   ; one float
        call    printf
; difference    
    movsd xmm2, [number1]   ; double precision float into xmm
    subsd xmm2, [number2]   ; subtract from xmm
        ; print the result
        movsd xmm0, [number1]
        movsd xmm1, [number2]
                mov rdi,f_dif
        mov rax,3   ; three floats
        call    printf
; multiplication  
    movsd xmm2, [number1]   ; double precision float into xmm
    mulsd xmm2, [number2]   ; multiply with xmm 
        ; print the result
                mov rdi,f_mul
                movsd xmm0, [number1]
        movsd xmm1, [number2]
        mov rax,3   ; three floats
        call    printf
; division
    movsd xmm2, [number1]   ; double precision float into xmm
    divsd xmm2, [number2]   ; divide xmm0 
        ; print the result
                mov rdi,f_div
                movsd xmm0, [number1]
        movsd xmm1, [number2]
        mov rax,1   ; one float
        call    printf
; squareroot
   sqrtsd xmm1, [number1]   ; squareroot double precision float in xmm
        ; print the result
                mov rdi,f_sqrt
                movsd xmm0, [number1]
        mov rax,2   ; one float
        call    printf
; exit
    mov rsp,rbp              
    pop rbp     ; undo the push at the beginning
    ret

结果如下:
The numbers are 9.000000 and 73.000000
The float sum of 9.000000 and 73.000000 is 82.000000
The float difference of 9.000000 and 73.000000 is -64.000000
The float product of 9.000000 and 73.000000 is 657.000000
The float division of 9.000000 by 73.000000 is 0.123288
The float squareroot of 9.000000 is 3.000000

对于浮点,参数传递用的就是xmm0,xmm1,等,这时候调用printf时指定的rax值就作用出来了,会告诉系统从哪里获取参数。
movsd 用于双精度,movss用于单精度。

相关文章

  • 汇编学习(4), 整数,栈,浮点

    本篇介绍 本篇介绍汇编的整数,浮点运算,还有栈。 整数运算 代码如下: add,sub 可以用于有符号,也可以用于...

  • python基础

    1整数与浮点数 在数据类型中我们学习了,整数和浮点数在计算机内部存储方式不同,整数运算永远是精确的,而浮点数则可能...

  • Python 入门演示

    简单的数学运算 整数相加,得到整数: 浮点数相加,得到浮点数: 整数和浮点数相加,得到浮点数: 变量赋值 Pyth...

  • chap1 --程序设计入门

    提示 整数值用%d输出,实数用%f输出。 整数/整数=整数, 浮点数/浮点数=浮点数 scanf中的占位符和变量的...

  • 最优除法

    题目: 给定一组正整数,相邻的整数之间将会进行浮点除法操作。例如, [2,3,4] -> 2 / 3 / 4 。但...

  • javaScript深入理解之数据类型

    类型 一、原始值(存放在栈内存中 stack,有序排列) Number(数字) Number:表示整数和浮点数 N...

  • Swift-数字类型转换、别名

    整数和浮点转换 整数和浮点数字类型之间的转换必须显式: 浮点到整数转换也必须显式。 整数类型可以使用Double或...

  • 格式化输出

    1、三种占位符: %s:可表示字符串,整数,浮点数 %d:可表示整数,浮点数保留整数部分 %f:可表示整数(浮点数...

  • 1. Python 变量 及 运算

    Numbers int 整数类型 如 : (2 , 4 , 20)float 浮点类型 如 : (5.0 , 1....

  • 字段类型选择

    数值: 整数,浮点数或小数 TINYINT (1) SMALLINT(2) MEDIUMINT(3) INT(4)...

网友评论

      本文标题:汇编学习(4), 整数,栈,浮点

      本文链接:https://www.haomeiwen.com/subject/vxyufdtx.html