On 2010-10-07, at 5:32 PM, Maxime Chevalier-Boisvert wrote:
Marc, I would like to ask your opinion on an implementation question.
If I want to load a 8 or 16 bit machine from memory into a 32/64 bit register, it seems I would have to do a mov from memory to the lower 8 or 16 bits of the register. However, one problem presents itself: possibly, the remainder of the register was already storing some other 32/64 bit value, and so the upper bits might be nonzero. This would imply that if I want to load a value smaller than the register, I would have to zero-out the register with xor first.
Do you know of a more efficient way of achieving this with just one instruction?
Yes... one instruction... reverse engineering can be fun!
% gcc -arch x86_64 -S -fomit-frame-pointer -O3 load.c;fgrep "(%rdi)" load.s movsbl (%rdi),%eax movswl (%rdi),%eax movl (%rdi), %eax movsbq (%rdi),%rax movswq (%rdi),%rax movslq (%rdi),%rax movq (%rdi), %rax % gcc -arch i386 -S -fomit-frame-pointer -O3 load.c;fgrep "(%eax)" load.s movsbl (%eax),%eax movswl (%eax),%eax movl (%eax), %eax % cat load.c typedef char s8; typedef short s16; typedef int s32; typedef long long s64;
s32 load_s8_s32(s8 *ptr) { return *ptr; } s32 load_s16_s32(s16 *ptr) { return *ptr; } s32 load_s32_s32(s32 *ptr) { return *ptr; } #ifndef i386 s64 load_s8_s64(s8 *ptr) { return *ptr; } s64 load_s16_s64(s16 *ptr) { return *ptr; } s64 load_s32_s64(s32 *ptr) { return *ptr; } s64 load_s64_s64(s64 *ptr) { return *ptr; } #endif