簡體   English   中英

為什么 strlen 的這個 REPNE SCASB 實現有效?

[英]Why does this REPNE SCASB implementation of strlen work?

為什么這段代碼有效?

http://www.int80h.org/strlen/說字符串地址必須在EDI寄存器中才能使scasb工作,但是這個匯編函數似乎沒有這樣做。

mystrlen匯編代碼:

global  mystrlen
mystrlen:
        sub             ecx, ecx
        not             ecx
        sub             al, al
        cld
        repne scasb
        neg             ecx
        dec             ecx
        dec             ecx
        mov             eax, ecx
        ret

C主:

int mystrlen(const char *);
int main()
{
    return (mystrlen("1234"));
}

匯編:

nasm -f elf64 test.asm
gcc -c main.c
gcc main.o test.o

輸出:

./a.out
echo $?
4

64 位 sysv 調用約定將第一個參數放入rdi 所以調用者main已經為你做了那個負載。 您可以檢查其匯編代碼並親自查看。

(答案由小丑提供)

問題中的代碼是 strlen 的 32 位版本,它僅部分地在 64b 環境中工作,有點“偶然”(因為大多數 SW 在現實中都可以工作,無論如何 ;) )。

64b 環境的一個意外影響是(在 System V ABI 中,64b linux 操作系統使用,其他 64b 平台可能遵循不同的調用約定,使此無效!),函數調用中的第一個參數通過rdi寄存器傳遞,並且scasb在 64b 模式下使用es:rdi ,所以這很自然地結合在一起(正如 Jester 的回答所說)。

其余 64b 環境效果較差,該代碼將返回 4+G 長字符串的錯誤值(我知道,在實際使用中極不可能發生,但可以通過提供如此長字符串的綜合測試進行嘗試)。

固定 64b 版本(也結束了例程利用 rax=0 在單個指令中同時執行neg ecxmov eax,ecx ):

global  mystrlen
mystrlen:
        xor       ecx,ecx    ; rcx = 0
        dec       rcx        ; rcx = -1 (0xFFFFFFFFFFFFFFFF)
        ; rcx = maximum length to scan
        xor       eax,eax    ; rax = 0 (al = 0 value to scan for)
        repne scasb          ; scan the memory for AL
        sub       rax,rcx    ; rax = 0 - rcx_leftover = scanned bytes + 1
        sub       rax,2      ; fix that into "string length" (-1 for '\0')
        ret

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM