汇编学习(10) 字符串

2022-12-19 08:34:02 浏览数 (2)

本篇介绍

本篇介绍下汇编中的字符串。

字符串

C语言中定义字符串是会以""结束,汇编中不会这样,只要是一块连续的内存,都可以认为是字符串。 下面是一段操作字符串的代码:

代码语言:javascript复制
; move_strings.asm
%macro prnt 2
    mov     rax, 1      ; 1 = write     
    mov     rdi, 1      ; 1 = to stdout         
    mov     rsi, %1                 
    mov     rdx, %2                     
    syscall
    mov rax, 1
    mov rdi, 1
    mov rsi, NL
    mov rdx, 1
    syscall

%endmacro

section .data                           
    length  equ 95
    NL db 0xa
    string1 db "my_string of ASCII:"
    string2 db 10,"my_string of zeros:"
    string3 db 10,"my_string of ones:"
    string4 db 10,"again my_string of ASCII:"
    string5 db 10,"copy my_string to other_string:"
    string6 db 10,"reverse copy my_string to other_string:"
section .bss
        my_string  resb length
    other_string resb length

section .text                           
    global main                     
main:
push    rbp
mov     rbp, rsp
;-----------------------------------------------------------------------
;fill the string with printable ascii characters
        prnt string1,18
        mov rax,32
        mov rdi,my_string
        mov rcx, length
str_loop1:  mov byte[rdi], al       ; the simple method
        inc rdi
            inc al
        loop str_loop1
        prnt my_string,length
;-----------------------------------------------------------------------
;fill the string with ascii 0's
        prnt string2,20
        mov rax,48
        mov rdi,my_string
        mov rcx, length
str_loop2:  stosb               ; no inc rdi needed anymore
        loop str_loop2
        prnt my_string,length
;-----------------------------------------------------------------------
;fill the string with ascii 1's
        prnt string3,19
        mov rax, 49
        mov rdi,my_string
        mov rcx, length
            rep stosb           ; no inc rdi and no loop needed anymore
        prnt my_string,length
;-----------------------------------------------------------------------
;fill the string again with printable ascii characters
        prnt string4,26
        mov rax,32
        mov rdi,my_string
        mov rcx, length
str_loop3:  mov byte[rdi], al       ; the simple method
        inc rdi
        inc al
        loop str_loop3
        prnt my_string,length
;-----------------------------------------------------------------------
;copy my_string to other_string 
        prnt string5,32
        mov rsi,my_string           ;rsi source
        mov rdi,other_string        ;rdi destination
        mov rcx, length
        rep movsb
        prnt other_string,length
;-----------------------------------------------------------------------
;reverse copy my_string to other_string 
        prnt string6,40
        mov rax, 48         ;clear other_string
        mov rdi,other_string
        mov rcx, length
            rep stosb           
        lea rsi,[my_string length-4]
        lea rdi,[other_string length]
        mov rcx, 27         ;copy only ten characters
        std                 ;std sets DF, cld clears DF
        rep movsb
        prnt other_string,length
leave
ret             
结果如下:
ngs$ ./move_strings 
my_string of ASCII
 !"#$%&'()* ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

my_string of zeros:
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

my_string of ones:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

again my_string of ASCII:
 !"#$%&'()* ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

copy my_string to other_string:
 !"#$%&'()* ,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

reverse copy my_string to other_string:
000000000000000000000000000000000000000000000000000000000000000000000abcdefghijklmnopqrstuvwxyz

stosb 用于循环赋值,每次一个字节,rcx中存放次数,rax存放源,rdi存放目的地址,每次循环rdi会自动增加1。 movsb 也是循环赋值,每次一个字节,rcx中存放次数,rsi存放源,rdi存放目的地址,每次rsi,rdi会增加1,如果设置DF标记,会每次减1。 再看一个比较字符串的例子:

代码语言:javascript复制
; strings.asm
extern  printf                                      
section .data                           
    string1     db "This is the 1st string.",10,0
    string2     db "This is the 2nd string.",10,0
    strlen2     equ $-string2-2
    string21    db "Comparing strings: The strings do not differ.",10,0
    string22    db "Comparing strings: The strings differ, "
            db "starting at position: %d.",10,0
    string3     db "The quick brown fox jumps over the lazy dog.",0
    strlen3     equ $-string3-2
    string33    db "Now look at this string: %s",10,0
    string4     db "z",0
    string44    db "The character '%s' was found at position: %d.",10,0
    string45    db "The character '%s' was not found.",10,0
    string46    db "Scanning for the character '%s'.",10,0
section .bss
section .text                           
    global main                     
main:
        push rbp
        mov     rbp,rsp
; print the 2 strings
    xor rax,rax
    mov rdi, string1
    call printf
    mov rdi, string2
    call printf   
; compare 2 strings ------------------------------------------------------------------------------
    lea rdi,[string1]
    lea rsi,[string2]
    mov rdx, strlen2
    call compare1
    cmp rax,0
    jnz not_equal1
;strings are equal, print
    mov rdi, string21
    call printf
    jmp otherversion
;strings are not equal, print
not_equal1:
    mov rdi, string22
    mov rsi, rax
    xor rax,rax
    call printf 
; compare 2 strings, other verstion -----------------------------------------------------
otherversion:
    lea rdi,[string1]
    lea rsi,[string2]
    mov rdx, strlen2
    call compare2
    cmp rax,0
    jnz not_equal2
;strings are equal, print
    mov rdi, string21
    call printf
    jmp scanning
;strings are not equal, print
not_equal2:
    mov rdi, string22
    mov rsi, rax
    xor rax,rax
    call printf 
; scan for a character in a string ---------------------------------------------------------------
; first print the string
    mov rdi,string33
    mov rsi,string3
    xor rax,rax
    call printf
; then print the search argument, can only be 1 character
    mov rdi,string46
    mov rsi,string4
    xor rax,rax
    call printf
scanning:
    lea rdi,[string3]   ;   string
    lea rsi,[string4]   ;   search argument
    mov rdx, strlen3
    call cscan
    cmp rax,0
    jz char_not_found
;character found, print
    mov rdi,string44
    mov rsi,string4
    mov rdx,rax
    xor rax,rax
    call printf
    jmp exit
;character not found, print
char_not_found: 
    mov rdi,string45
    mov rsi,string4
    xor rax,rax
    call printf
exit:
leave
ret

; FUNCTIONS ======================================================================================

; function compare 2 strings ---------------------------------------------------------------------
compare1:   mov rcx, rdx
        cld
cmpr:   cmpsb
        jne notequal
        loop cmpr
        xor rax,rax
        ret
notequal:   mov rax, strlen2
        dec rcx     ;compute position
        sub rax,rcx ;compute position
        ret
        xor rax,rax
        ret
;------------------------------------------------------------------------------
; function compare 2 strings ---------------------------------------------------------------------
compare2:   mov rcx, rdx
        cld
        repe cmpsb
        je equal2
        mov rax, strlen2
        sub rax,rcx ;compute position
        ret
equal2: xor rax,rax
        ret
;------------------------------------------------------------------------------
;function scan a string for a character
cscan:  mov rcx, rdx
        lodsb
        cld
        repne scasb
        jne char_notfound
        mov rax, strlen3
        sub rax,rcx ;compute position
        ret
char_notfound:  xor rax,rax
        ret
结果如下:           
./strings 
This is the 1st string.
This is the 2nd string.
Comparing strings: The strings differ, starting at position: 13.
Comparing strings: The strings differ, starting at position: 13.
Now look at this string: The quick brown fox jumps over the lazy dog.
Scanning for the character 'z'.
The character 'z' was found at position: 38

comsb用来比较rsi,rdi指向需要比较的字符串地址,结果会存放到ZF标记中,如果是1表示相等,0则反之, 需要借助loop 才能比较ecx指定的长度。 repe(repeat while equal), repne(repeat while not equal),借助comsb,scasb就可以查找字符串了。

0 人点赞