I just got into reversing, i'm a bit puzzled by a part of the following code. I know what its doing, from a technical aspect, but i don't really understand why its doing it.

This is the part I have a question about.

seg005:292F                 test    si, 1           ; ?
seg005:2933                 jz      short loc_21587
seg005:2935                 movsb                   ; move byte DS:SI to ES:DI
seg005:2936                 dec     cx

Why check to see if the LSB is set and, if it is, move only one byte before moving the rest of the string? Does this have to do with alignment? That's the best explanation I can think up.

The entire function is below. All comments and names were filled out by me. Any other notes/comments on them or the function as a whole are appreciated. Thanks.

seg005:290A ; =============== S U B R O U T I N E =======================================
seg005:290A ; Attributes: bp-based frame
seg005:290A StringConcat    proc far                ; CODE XREF: sub_1FFED+16P
seg005:290A                                         ; sub_1FFED+3AP ...
seg005:290A Destination     = word ptr  6
seg005:290A Source          = word ptr  8
seg005:290A                 push    bp
seg005:290B                 mov     bp, sp
seg005:290D                 push    si              ; save SI
seg005:290E                 push    di              ; save DI
seg005:290F                 cld                     ; clear direction flag.
seg005:2910                 mov     di, [bp+Destination]
seg005:2913                 push    ds              ; move ds....
seg005:2914                 pop     es              ; ...into es
seg005:2915                 mov     dx, di
seg005:2917                 xor     al, al          ; al = search char. 0x0
seg005:2919                 mov     cx, 0FFFFh
seg005:291C                 repne scasb
seg005:291E                 lea     si, [di-1]      ; last char in string
seg005:2921                 mov     di, [bp+Source]
seg005:2924                 mov     cx, 0FFFFh
seg005:2927                 repne scasb
seg005:2929                 not     cx              ; length of string
seg005:292B                 sub     di, cx          ; move back to the start of the string?
seg005:292D                 xchg    si, di          ; si = start of source string.
seg005:292D                                         ; di = end ofdestination string
seg005:292F                 test    si, 1           ; ?
seg005:2933                 jz      short loc_21587
seg005:2935                 movsb                   ; move byte DS:SI to ES:DI
seg005:2936                 dec     cx
seg005:2937 loc_21587:                              ; CODE XREF: StringConcat+29j
seg005:2937                 shr     cx, 1           ; Divide cx by 2. Moving words, not bytes, so half the size
seg005:2939                 rep movsw               ; move words DS:SI to ES:DI CX times
seg005:293B                 jnb     short loc_2158E
seg005:293D                 movsb
seg005:293E loc_2158E:                              ; CODE XREF: StringConcat+31j
seg005:293E                 xchg    ax, dx
seg005:293F                 pop     di
seg005:2940                 pop     si
seg005:2941                 pop     bp
seg005:2942                 retf
seg005:2942 StringConcat    endp

It's a minor speed optimization. The main loop for moving characters use movsw (move words) which was probably slightly faster than moving bytes. However, in case the number of bytes is odd, one byte would be left uncopied, and that's why there is an extra mosvb before and after it (so the extra byte is moved before or after, depending on alignment of the string address).

  • there is a performance hit to copying from a misaligned source address, hence the need to align it first – peter ferrie May 23 '16 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.