0

I am new to assembly, and when I studied on the internet, I found the following code, but I don't know why push eax is not written before mov eax, [ebp+8].

; char* removerng(char* s, char a, char b)
; removes (in place) characters from a to b in string s
    section .text
    global  removerng
removerng:
    ; prologue
    push    ebp
    mov     ebp, esp
    push    ebx ;<- ebx instead of eax?
    push    esi
    push    edi

    ; body <- we don't need eax?
    mov eax, [ebp+8]; load string into return address
    mov esi, [ebp+8]; last char checked
    mov edi, [ebp+8]; last char placed

loop:
    mov bh, [esi]; current char
    inc esi
    test    bh, bh; test for end of string
    jz  fin
    cmp bh, [ebp+12] 
    jl  keep
    cmp bh, [ebp+16]
    jg  keep
    jmp loop

keep:
    mov [edi], bh
    inc edi
    jmp loop

fin:
    mov [edi], bh

    ;epilogue
    pop edi
    pop esi
    pop ebx
    mov esp, ebp
    pop ebp
    ret

Does this mean we can use both push ebx and push eax Could any one help me?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    EAX is call-clobbered, EBX is call-preserved (like ESI and EDI). (And the function uses BH for no reason, so it has to save / restore EBX even though EDX and ECX are still unused.) It returns in EAX, so it certainly doesn't need to save and restore the caller's value! – Peter Cordes May 09 '22 at 18:09
  • [How to understand volatile and non-volatile registers?](https://stackoverflow.com/q/32002157/327083) – J... May 09 '22 at 18:09
  • [Does it matter which registers you use when writing assembly?](https://stackoverflow.com/q/59869218/327083) – J... May 09 '22 at 18:10
  • 2
    Note that `EAX` is often used for the return value of the function, and this is what the comment appears to be saying: `mov eax, [ebp+8]; load string into return address`. – Fred Larson May 09 '22 at 18:11
  • [What's the advantage of having nonvolatile registers in a calling convention?](https://stackoverflow.com/q/10392895/327083) – J... May 09 '22 at 18:12
  • This is a pretty clunky example. Specifically, never write code like `jg keep` / `jmp loop` / `keep:`. That could just be a `jng loop` with fall-through to the next block. And don't use high-8-bit registers for no reason; AH/BH/CH/DH are slower than normal registers on some CPUs. – Peter Cordes May 09 '22 at 18:13
  • 1
    There are also various optimizations it could make, e.g. a range-check with sub / cmp / ja instead of two separate compare and branch. And keeping the values to compare against in registers instead of reloading from the stack for every char in the string. The in-place filtering algorithm is good, though, although could be optimized with a read-only scan for the first character to remove. – Peter Cordes May 09 '22 at 18:25

0 Answers0