Discussion:
Assembling 16 bit immediates using GAS?
(too old to reply)
s***@crayne.org
2006-01-02 21:24:21 UTC
Permalink
I am using gnu assembler 2.13 and targeting an x86 architecture... My
desired behavior is that I want to push a 16 bit immediate value onto a
stack, and then call a subroutine which will pop that same value off
into ax. I do not want to move the immediate into ax and then push ax.
That uses more instructions. :)

Opcode 68 achieves this, and places a 16b immediate onto the stack.
0x68 is also push imm32.
Opcode 6A is push 8b immediate

GAS seems to pick the instruction based on the length of my constant.
If I specify a constant that can be represented in 8 bits, then GAS
selects the imm8 version of the instruction. Even if I try to override
the instruction size, GAS picks 0x6a for the opcode. If I select a 16b
immediate that cannot be represented in 8bits, then GAS picks opcode
0x68.

If I handcode my instruction, as is the case on listing-line 54, I can
get an opcode 68.

Is there a mechanism to force a 16b sign extended (in this case 0
extended) immediate push without handcoding the assembly? I'd prefer to
use intel syntax, but I'll use AT&T if necessary. Maybe this is more of
a sign extending/variable sizing question?

Thanks!
--eric


***@ldclo6401> as -v
GNU assembler version 2.13.2.1 (x86_64-unknown-linux-gnu) using BFD
version 2.13.2.1

49 .intel_syntax
50 0000 666A0C pushw 12
51 0003 66683412 pushw 0x1234
52 0007 666A09 pushw 0x0009
53 000a 6668000C .byte 0x66, 0x68, 0x00, 0x0c #handcode the
push word immediate
54 .att_syntax
55 000e 6A0D pushl $13
56 0010 53 pushl %ebx
57 .intel_syntax noprefix
58 0011 666A0D push (word ptr 13)
Rod Pemberton
2006-01-03 09:30:25 UTC
Permalink
----- Original Message -----
From: <***@crayne.org>
Newsgroups: comp.lang.asm.x86
Sent: Monday, January 02, 2006 4:24 PM
Subject: Assembling 16 bit immediates using GAS?
Post by s***@crayne.org
I am using gnu assembler 2.13 and targeting an x86 architecture... My
desired behavior is that I want to push a 16 bit immediate value onto a
stack, and then call a subroutine which will pop that same value off
into ax. I do not want to move the immediate into ax and then push ax.
That uses more instructions. :)
Opcode 68 achieves this, and places a 16b immediate onto the stack.
0x68 is also push imm32.
Opcode 6A is push 8b immediate
You are slightly confused. 6A is coded with a 8b immediate. Without a size
override prefix 0x66, it pushes a 16-bit value for RM and a 32-bit for PM.
With a size override prefix 0x66, it pushes a 32-bit value for RM and a
16-bit value for PM. The stack always pushes/pops 16-bit or 32-bit values.
A single (8-bit) byte can't be pushed onto the stack. You can look at the
pseudo-code Intel or AMD provides in their PDF's.

push/pop - uses default segment size 16-bit/32-bit
pushw/popw - push/pop a word, corrected for 16-bit/32-bit, i.e., will have
size override prefix when needed
pushf/popf - push/pop a doubleword (32-bit), correct for 16-bit/32-bit
segment, i.e., will have a size override prefix when needed

***snip***

666A0C pushw 12 - this pushes 16-bits onto a 32-bit (PM) stack
66683412 pushw 0x1234 - this pushes 16-bits onto a 32-bit (PM) stack
666A09 pushw 0x0009 - this pushes 16-bits onto a 32-bit (PM) stack
6668000C .byte 0x66, 0x68, 0x00, 0x0c - this pushes 16-bits onto a 32-bit
(PM) stack
6A0D pushl $13 - this pushes 32-bits onto a 32-bit (PM) stack.
53 pushl %ebx - this pushes 32-bits of register onto a 32-bit (PM) stack.
666A0D push (word ptr 13) - this pushes 16-bits onto a 32-bit (PM) stack

Note that all but one above push 16-bits onto a stack which is in 32-bit
mode. The stack can be in 16-bit mode (RM) or 32-bit mode (PM). When in
RM, 16-bit values are pushed by default unless there is a size override
prefix. With the size override prefix, 32-bit values are pushed. When in
PM, 32-bit values are pushed by default unless there is a size override
prefix. With the size override prefix, 16-bit values are pushed.

NASM will disassemble 666A0D push (word ptr 13) as o16 push byte +0xd.
But the byte doesn't refer to the size of the value being pushed onto the
stack, but that the instruction coding is 8-bit...

Hope that helped...

Rod Pemberton

PS. It'd be nice if clax86-***@crayne.org came up in the reply box
instead of ***@crayne.org ...
Rod Pemberton
2006-01-03 09:40:04 UTC
Permalink
----- Original Message -----
From: "Rod Pemberton" <***@comcast.com>
To: <clax86-***@crayne.org>
Sent: Tuesday, January 03, 2006 4:30 AM
Subject: Re: Assembling 16 bit immediates using GAS?
Post by Rod Pemberton
push/pop - uses default segment size 16-bit/32-bit
pushw/popw - push/pop a word, corrected for 16-bit/32-bit, i.e., will have
pushf/popf - push/pop a doubleword (32-bit), correct for 16-bit/32-bit
Ooops, correction (too much Watcom assembly lately):
pushl/popl, for the last one...

RP
s***@crayne.org
2006-01-04 19:26:30 UTC
Permalink
thanks for replying Rod. If you'll notice in my listing, I use pushw.
Unfortunately gas still selects the Byte variant opcode (6a). The only
way I get a word pushed imm16 is if I use pushw and use a
constant/immediate that absolutely must be expressed using 16b.

E.g.
pushw 0x12 (will select 6a opcode)
pushw 0x0012 (will select 6a opcode)
pushw 0x1234 (will select the 68 opcode word/long word)

--eric
Frank Kotler
2006-01-04 23:04:29 UTC
Permalink
Post by s***@crayne.org
pushw 0x12 (will select 6a opcode)
It's not clear to me whether you understand that this *does* push a
word. The "byte" (actually signed byte) refers only to how the "12" is
stored - as 12 or as 12 00 - you get the word 12 on the stack in either
case.

If you really need that zero in your code... do you want it bad enough
to switch to Nasm? :)

o16 push strict word 12

....will do what you want - even with the "-O" switch...

Best,
Frank
s***@crayne.org
2006-01-04 22:28:26 UTC
Permalink
Post by s***@crayne.org
thanks for replying Rod. If you'll notice in my listing, I use pushw.
Unfortunately gas still selects the Byte variant opcode (6a).
You haven't explained *why* you need the Word opcode. As Rod pointed
out, the actual value pushed onto the stack is 16 bits (or 32 bits)
irrespective of whether the Byte or the Word opcode is used, so the
only reason I can think of why you might not want to use the Byte
variant is to allow you to patch the code later to push a larger value.
Is that it? Are you writing self-modifying code or something?

Richard.
http://www.rtrussell.co.uk/
BBC BASIC for Windows: BASIC with a built-in run-time x86 assembler.
Rod Pemberton
2006-01-05 03:49:02 UTC
Permalink
----- Original Message -----
From: <***@crayne.org>
Newsgroups: comp.lang.asm.x86
Sent: Wednesday, January 04, 2006 5:28 PM
Subject: Re: Assembling 16 bit immediates using GAS?
Post by s***@crayne.org
Post by s***@crayne.org
thanks for replying Rod. If you'll notice in my listing, I use pushw.
Unfortunately gas still selects the Byte variant opcode (6a).
You haven't explained *why* you need the Word opcode. As Rod pointed
out, the actual value pushed onto the stack is 16 bits (or 32 bits)
irrespective of whether the Byte or the Word opcode is used, so the
only reason I can think of why you might not want to use the Byte
variant is to allow you to patch the code later to push a larger value.
Is that it? Are you writing self-modifying code or something?
If that's the case why he *needs* 68 when 6A does what he requested in his
first post, he could do something like this (I'm not sure if this is
correct....help?) :

pushw $0x12 # 6A puts 00 12 (or is it 12 00 ?) on the
stack
movb 2(%esp),$0xAA # replace 00 with AA, offset could be 2 or 0, OK, I'm
endianess confused here...
...
call something
popw ax


Sorry, you'll need to work out the stack byte order...


Rod Pemberton

Continue reading on narkive:
Loading...