# First steps with amd64 assembly

I try to learn amd64 assembler. This is the first thing I tried. This piece of assembly should replicate the functionality of the following piece of C code, which turns a binary sha-256 hash into a human readable form.

### assembly code

1:  .ascii "0123456789abcdef"
.global show_hash
show_hash:
.type show_hash @function
.func show_hash
mov 32,%ecx .p2align 2 0: xor %eax,%eax lodsb mov %eax,%edx shr4,%al
and \$15,%dl
mov 1b(%rax),%al
mov 1b(%rdx),%dl
mov %bl,%ah
stosw
dec %ecx
jnz 0b
mov %cl,(%rdi)
ret
.endfunc


### C code

void show_hash(char *dst, unsigned char *src) {
static const char *lookup = "0123456789abcdef";
char lo, hi, byte;
int i = 32;

do {
byte = *src++;
hi = lookup[byte >> 4];
lo = lookup[byte & 0xf];
*dst++ = hi;
*dst++ = lo;
} while (i--);
}


Am I doing it right? I tried to move the lookup table (label 1) into .section rodata, but all references to it were changed to 0 in the linked program, so I put it into the text section for now.

• I don't think you can access data unless it's in the data segment. – Hawken Oct 22 '12 at 23:42
• @Hawken How do you come to this conclusion? – FUZxxl Oct 23 '12 at 5:02
• all memory is referenced using the segment specified by %ds or if it's on the stack, %ss. Unless you have personally set the segment register, mov %cs,%ds, or your assembler is adding a custom segment offset, you can't read from outside .data. I don't know if modern OSs allow you to read from .text at all even if you did. – Hawken Oct 26 '12 at 20:43
• @Hawken You see that this code is written for x86-64 linux which uses a flat memory modell? All segment registers except %fs and %gs which serve a special purpose are set to zero. – FUZxxl Oct 26 '12 at 20:48
• Hmm, I did not know that. wiki.osdev.org/X86-64 contains information on this for anyone else who did not know. – Hawken Oct 26 '12 at 21:43

• If show_hash uses cdecl calling conventions you should preserve registers like %bl, and read the input parameter values from the stack into esi and edi.
• I don't understand the syntax of mov 1b(%rax),%al: is it reading from the lookup array defined at label 1:? On re-reading, I think it is; however that will only work if the most-significant bytes of rax and rdx are all zero; perhaps you should initialize them as you did using xor %eax,%eax
(apparently xor %eax,%eax will clear the whole of %rax)
• You're using stosw which writes two bytes (two ASCII characters) a time; but %ah contains a value from %bl, and %bl wasn't previously initialized? I think that statement should have been mov %dl,%ah not mov %bl,%ah; or perhaps you could have done mov 1b(%rdx),%ah directly.
• The function ends with mov %cl,(%rdi) to null-terminate the string; that is clever but could use a comment (it took me a bit to figure out). Most of the questions either have good comments, or answer which say that they should have good comments.
• In that case the only error I see is the typo involving %bl instead of %dl. – ChrisW Mar 6 '14 at 20:40