[Nasm-devel] Is that a bug? add ax, 10

C. Masloch pushbx at ulukai.org
Fri Mar 31 07:01:32 PDT 2023


On at 2023-03-30 15:24 +0000, Tim Petschauer wrote:
> Hey,
> 
> after some thinking before falling asleep, I now believe my assumptions 
> make a lot less sense.
> 
> Since the width of the immediate data added to the accumulator depends 
> on the accumulator used, "add reg_ax, imm" instruction would use 3 bytes 
> for 8 bit immediates anyways. So there are no savings here.

Correct. There is no single-byte "add ax, imm8" opcode, only the 
single-byte "add ax, imm16" (plus the 2-byte imm16 itself) and the 
two-byte "add r/m16, imm8" (plus the 1-byte imm8).

> However, I'm still interested in why the add rm16, imm8 instruction is 
> choosen in these cases over the add reg_ax, imm? Is it because there's 
> no need to widen the immediate to 16 bits in that case?

It is simply up to the assembler to choose one or the other, and NASM 
happens to choose the sign-extended-immediate "add r/m16, imm8" form by 
default. (All assemblers have to make similar encoding choices for a 
number of cases, and A86 famously had a specific pattern of choices -- 
supposedly to uncover unregistered uses of the assembler.)

You can make NASM choose the "add ax, imm16" single-byte form instead by 
specifying the operand as "strict word 1". NASM does not offer any way 
to specify use of a ModR/M form where an equally small or smaller 
non-ModR/M form exists.

Here's an example of adding 1 to ax. (Of course, for the specific case 
of adding 1 in particular, "inc ax" may be the better choice. But it 
doesn't modify the Carry Flag, unlike "add".)

$ nasm -v
NASM version 2.16rc0 compiled on Sep  5 2022
$ cat test.asm
add ax, 1
add ax, strict word 1
add ax, strict byte 1

$ nasm test.asm -l /dev/stderr
      1 00000000 83C001                  add ax, 1
      2 00000003 050100                  add ax, strict word 1
      3 00000006 83C001                  add ax, strict byte 1
      4
$


Regards,
ecm

> 
> Best regards
> 
> Tim
> 
> Am 29.03.23 um 21:52 schrieb Tim Petschauer:
>> @mods:
>>
>> Sorry, used the wrong sender address the first time.
>>
>>
>> Hey there,
>>
>>
>> I stumbled upon something that might be a bug in the selection of the 
>> correct, i.e. shortest, bytecode for adding 8 bit immediates to a 
>> larger accumulator. At least in the 'bits 16' mode which I'm using at 
>> the moment.
>>
>> Examples follow:
>>
>> bits 16
>>
>> add ax, 10    ---> 83 c0 0a
>>
>> add ax, 1000 ---> 05 e8 03
>>
>> So for the first instruction the opcode for "add rm16, imm8" is 
>> choosen, but I think "add reg_ax, imm" can be a byte shorter if it is 
>> not wide.
>>
>> The second instruction is working as expected.
>>
>>
>> So if that's a bug, I have a couple thoughts on how to fix it:
>>
>> Since the instuction matching works by moving sequentially through all 
>> the ADD instructions and "add rm16, imm8" is listed before the "add 
>> reg_ax, imm" the matcher would stop at the first match and just use 
>> what it had found.
>>
>> However, since there is not explicit "add reg_ax, imm8" opcode in the 
>> instruction data files, the accumulator addition might produce 3 bytes 
>> anyway and all of this wouldn't matter, except someone saw the need to 
>> implement such an opcode (or maybe the "add reg_ax, imm8" already can 
>> handle 8 bits).
>>
>> I skimmed the data files for the related instructions (or, adc, sbb 
>> ...) and they seem to have the same structure, so this probably isn't 
>> a bug. But I wanted to ask about it anyway so I might get an answer 
>> why this handling of 8bit adds to a 16 bit accumulator was choosen.
>>
>> Best regards
>>
>> Tim Petschauer
>>
>>
>> _______________________________________________
>> Nasm-devel mailing list
>> Nasm-devel at nasm.us
>> https://lists.nasm.us/nasm-devel
> _______________________________________________
> Nasm-devel mailing list
> Nasm-devel at nasm.us
> https://lists.nasm.us/nasm-devel



More information about the Nasm-devel mailing list