2022年08月

2022年08月发布的文章
  • 汇编语言Irivne64字符串过程详解[附带实例]

    下面将一些比较重要的字符串处理过程从 Irvine32 链接库转换为 64 位模式。变化非常简单,删除堆栈参数,并将所有的 32 位寄存器都替换为 64 位寄存器。

    下表列出了这些字符串过程、过程说明及其输入输出。

    Str_compare 比较两个字符串
    输入参数:RSI 为源串指针,RDI 为目的串指针
    返回值:若源串 < 目的串,则进位标志位 CF=1;若源串 = 目的串,则零标志位 ZF=1;若源串 > 目的串,则 CF=0 且 ZF=0
    Str_copy 将源串复制到目的指针指向的位置
    输入参数:RSI 为源串指针,RDI 指向被复制串将要存储的位置
    Str_length 返回空字节结束字符串的长度
    输入参数:RCX 为字符串指针
    返回值:RAX 为该字符串的长度

    Str_compare 过程中,RSI 和 RDI 是输入参数的合理选择,因为字符串比较循环会用到它们。使用这两个寄存器参数能在过程开始时避免将输入参数复制到 RSI 和 RDI 寄存器中:

    ;------------------------------------
    ;Str_compare
    ;比较两个字符串
    ;接收:RSI 为源串指针
    ;     RDT 为目的串指针
    ;返回:若字符串相等,ZF 置 1
    ;      若源串 < 目的串,CF 置 1
    ;------------------------------------
    Str_compare PROC USES rax rdx rsi rdi
    L1: mov al,[rsi]
        mov dl,[rdi]
        cmp al, 0            ; string1 结束?
        jne L2               ; 否
        cmp dl, 0            ;是:string2 结束?
        jne L2               ;否
        jmp L3               ;是:退出且 ZF=1
    L2: inc rsi              ;指向下一个字符
        inc rdi
        cmp al,dl            ;字符相等?
        je L1                ;是:继续循环
                             ;否:退出并设置标志位
    L3: ret
    Str_compare ENDP

    注意,PROC 伪指令用 USES 关键字列出了所有需要在过程开始时入栈、在过程时返回出栈的寄存器。

    Str_copy 过程用 RSI 和 RDI 接收字符串指针:

    ;-------------------------------------
    ;Str_copy
    ;复制字符串
    ;接收:RSI 为源串指针
    ;     RDI 为目的串指针
    ;返回:无
    ;-------------------------------------
    Str_copy PROC USES rax rex rsi rdi
        mov rex,rsi               ;获得源串长度
        call Str_length           ;RAX 返回长度
        mov rex,rax               ;循环计数器
        inc rex                   ;有空字节,加 1
        cld                       ;方向为正向
        rep movsb                 ;复制字符串
        ret
    Str_copy ENDP

    Str_length 过程用 RCX 接收字符串指针,然后循环扫描该字符串直到发现空字节。字符串长度用 RAX 返回:

    ;-------------------------------------
    ;Str_length
    ;计算辜符串长度
    ;接收:RCX 指向字符串
    ;返回:RAX 为字符串长度
    ;-------------------------------------
    Str_length PROC USES rdi
        mov rdi,rex           ;获得指针
        mov eax,0             ;字符计数
    L1:
        cmp BYTE PTR [rdi],0  ;字符串结束?
        je L2                 ;是:退出
        inc rdi               ;否:指向下一个字符
        inc rax               ;计数器加 1
        jmp L1
    L2: ret                   ;RAX 返回计数值
    Str_length ENDP

    一个简单的测试程序

    下面的测试程序调用了 64 位的 Str_length、Str_copy 和Str_compare 过程。虽然程序中没有显示字符串的语句,但是建议在 Visual Studio 凋试器中运行,这样就可以查看内存窗口、寄存器和标志位。

    ; 测试 Irvine64 字符串程序
    Str_compare        proto
    Str_length        proto
    Str_copy        proto
    ExitProcess     proto
    
    .data
    source byte "AABCDEFGAABCDFG",0      ; 大小为 15
    target byte 20 dup(0)
    .code
    main proc
        mov   rax,offset source
        call  Str_length                ; 用 RAX 返回长度
    
        mov   rsi,offset source
        mov   rdi,offset target
        call  str_copy
    
    ; 由于刚刚才复制了字符串,因此它们应该相等
       
        call  str_compare                ; ZF = 1, 字符串相等
    
    ; 修改目的串的第一个字符,再比较两个字符串
    ; compare them again:
    
        mov   target,'B'
        call  str_compare                ; CF = 1, 源串 < 目的串
       
        mov   ecx,0
        call  ExitProcess
    main ENDP

更多...

加载中...