Mail Archives: djgpp/2001/05/22/10:33:12
This message is in MIME format.
---MOQ9905399804a11db13bd3a5e7e570a5b518e5a0f9e
Content-Type: text/plain
Content-Transfer-Encoding: 8bit
When experimenting with the .code16 and .code16gcc
directives in order to compile
C code in 16-bit real mode, I found that some constants
that appeared in the C
code as parameters to a procedure were being sign
extended as if by assignment from
\\\\\\\\\\\\\\\'signed short\\\\\\\\\\\\\\\' to \\\\\\\\\\\\\\\'signed
long\\\\\\\\\\\\\\\'. However,
the
parameters were unsigned longs like
0x8000UL, passed as arguments to a procedure that
takes \\\\\\\\\\\\\\\'dwords\\\\\\\\\\\\\\\', defined as
\\\\\\\\\\\\\\\'typedef unsigned long dword\\\\\\\\\\\\\\\'.
Examination of the
assembly output showed that the
compiler was generating the correct opcodes with
correct instructions (because the
.code16gcc was given with an __asm__ directive, the
compiler could not know that
the code would be assembled to an USE16 segment).
Examination through DEBUG showed
that the constant was sign extended in the binary
opcodes, though not in the assembly
output. This means that, when assembling with
the .code16gcc directive, \\\\\\\\\\\\\\\'as\\\\\\\\\\\\\\\' incorrectly
sign-extends 32-bit constants that fit in a 16-bit word
and have bit 15 set (like
0x00008000UL) (that is, the most significant bit is bit
15), at least with
\\\\\\\\\\\\\\\'pushl $constant\\\\\\\\\\\\\\\' , \\\\\\\\\\\\\\\'movl
$constant, r/m32
\\\\\\\\\\\\\\\',
and \\\\\\\\\\\\\\\'andl/orl $constant, r/m32\\\\\\\\\\\\\\\'
instructions. The file \\\\\\\\\\\\\\\'as_bug.s\\\\\\\\\\\\\\\' is a
minimal
example
that reproduces the bug.
The binary output is the following:
66 68 00 80 FF FF /* assembled from \\\\\\\\\\\\\\\'pushl
$0x8000
\\\\\\\\\\\\\\\',
but is really \\\\\\\\\\\\\\\'pushl $0xFFFF8000\\\\\\\\\\\\\\\' */
66 58 /* popl %eax */
66 83 E0 FF /* assembled from \\\\\\\\\\\\\\\'andl
$0xFFFF, %eax\\\\\\\\\\\\\\\', but is really \\\\\\\\\\\\\\\'andl
$0xFFFFFFFF, %
eax\\\\\\\\\\\\\\\'
*/
66 B8 FF FF FF FF /* assembled from \\\\\\\\\\\\\\\'movl
$0xFFFF, %eax\\\\\\\\\\\\\\\', but is really \\\\\\\\\\\\\\\'movl
$0xFFFFFFFF, %
eax\\\\\\\\\\\\\\\'
*/
90 /* NOPs for padding */
90
90
90
90
66 68 00 80 FF FF /* assembled from \\\\\\\\\\\\\\\'pushl
$0xFFFF8000\\\\\\\\\\\\\\\' */
66 58 /* popl %eax */
66 83 E0 FF /* assembled from \\\\\\\\\\\\\\\'andl
$0xFFFFFFFF, %eax\\\\\\\\\\\\\\\' */
66 B8 FF FF FF FF /* assembled from \\\\\\\\\\\\\\\'movl
$0xFFFFFFFF, %eax\\\\\\\\\\\\\\\' */
90 /* NOPs for padding */
90
90
90
90
B8 00 4C /* Normal exit with INT
21h */
CD 21
Constants assembled in section \\\\\\\\\\\\\\\'.data\\\\\\\\\\\\\\\'
with
\\\\\\\\\\\\\\\'.long\\\\\\\\\\\\\\\'
are
not affected by .code16gcc, so
a partial workaroud is to store constants as
initialized global variables, which are then
accessed from code. However, this does not work when
garbage in the high word of a
32-bit register needs to be masked out with, for
example, \\\\\\\\\\\\\\\'andl $65535, %eax\\\\\\\\\\\\\\\'. This
instruction is emitted every time a function returns
with a 16-bit value in a 32-bit register.
Output of \\\\\\\\\\\\\\\'as --version\\\\\\\\\\\\\\\':
-------------------------
GNU assembler 2.9.5
Copyright 1997 Free Software Foundation, Inc.
This program is free software; you may redistribute it
under the terms of
the GNU General Public License. This program has
absolutely no warranty.
This assembler was configured for a target of `i386-pc-
msdosdjgpp\\\\\\\\\\\\\\\'.
Patches applied to \\\\\\\\\\\\\\\'as\\\\\\\\\\\\\\\' source:
-------------------------------
none
Machine in use:
---------------
AMD K5-PR133 at 100 MHz, Award BIOS 1996.
Operating system:
-----------------
Microsoft Windows 95 4.00.950a
IE 5 5.00.2314.1003
Compiler used to compile \\\\\\\\\\\\\\\'as\\\\\\\\\\\\\\\':
------------------------------
gcc 2.9.5
Makefile used to invoke \\\\\\\\\\\\\\\'as\\\\\\\\\\\\\\\':
-----------------------------
OBJECTS =as_bug.o
CC =gcc
as_bug.com: $(OBJECTS) comfile.djl
ld -o as_bug.com -Tcomfile.djl $(OBJECTS) --
oformat binary -M
.s.o:
$(CC) -c -o $*.o $*.s
Contents of \\\\\\\\\\\\\\\'comfile.djl\\\\\\\\\\\\\\\':
--------------------------
OUTPUT_FORMAT(\\\\\\\\\\\\\\\"coff-go32\\\\\\\\\\\\\\\")
ENTRY(_start)
SECTIONS
{
.text 0x100 :
{
*(.text)
. = ALIGN(0x10);
}
.data . :
{
*(.data)
. = ALIGN(0x10);
}
.bss . :
{
*(.bss)
*(COMMON)
. = ALIGN(0x10);
}
}
Assembly input file \\\\\\\\\\\\\\\'as_bug.s\\\\\\\\\\\\\\\' (minimal
example
that
reproduces bug):
--------------------------------------------------------
--
.code16gcc
.text
.globl _start
_start:
pushl $0x8000 /* <-- 0x8000 is being
sign extended into 0xFFFF8000 */
popl %eax /* Restore
stack pointer */
andl $0xFFFF, %eax /* <-- incorrectly
assembled into \\\\\\\\\\\\\\\'andl $0xFFFFFFFF, %eax\\\\\\\\\\\\\\\' */
movl $0xFFFF, %eax /* <-- incorrectly
assembled into \\\\\\\\\\\\\\\'movl $0xFFFFFFFF, %eax\\\\\\\\\\\\\\\' */
nop /* Padding
included to get \\\\\\\\\\\\\\\'objdump --disassemble\\\\\\\\\\\\\\\'
into
synch */
nop /* so that
opcodes can be checked for equality */
nop
nop
nop
/* The above code assembles exactly like the
one below (use a hex dump or disassembler to check). */
pushl $0xFFFF8000
popl %eax
andl $0xFFFFFFFF, %eax
movl $0xFFFFFFFF, %eax
nop
nop
nop
nop
nop
movw $0x4c00, %ax /* Normal exit through
INT 21h */
int $0x21
(All files are given as attachments to this report)
-----------------------------------------------------------------
Este mail fue enviado a traves del servidor de Webmail de la FIEC
---MOQ9905399804a11db13bd3a5e7e570a5b518e5a0f9e
Content-Type: text/plain; name="as_bug.s"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename="as_bug.s"
.code16gcc
.text
.globl _start
_start:
pushl $0x8000 /* <-- 0x8000 is being sign extended into 0xFFFF8000 */
popl %eax /* Restore stack pointer */
andl $0xFFFF, %eax /* <-- incorrectly assembled into 'andl $0xFFFFFFFF, %eax' */
movl $0xFFFF, %eax /* <-- incorrectly assembled into 'movl $0xFFFFFFFF, %eax' */
nop /* Padding included to get 'objdump --disassemble' into synch */
nop /* so that opcodes can be checked for equality */
nop
nop
nop
/* The above code assembles exactly like the one below (use a hex dump or disassembler to check). */
pushl $0xFFFF8000
popl %eax
andl $0xFFFFFFFF, %eax
movl $0xFFFFFFFF, %eax
nop
nop
nop
nop
nop
movw $0x4c00, %ax /* Normal exit through INT 21h */
int $0x21
---MOQ9905399804a11db13bd3a5e7e570a5b518e5a0f9e
Content-Type: text/plain; name="comfile.djl"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename="comfile.djl"
OUTPUT_FORMAT("coff-go32")
ENTRY(_start)
SECTIONS
{
.text 0x100 :
{
*(.text)
. = ALIGN(0x10);
}
.data . :
{
*(.data)
. = ALIGN(0x10);
}
.bss . :
{
*(.bss)
*(COMMON)
. = ALIGN(0x10);
}
}
---MOQ9905399804a11db13bd3a5e7e570a5b518e5a0f9e
Content-Type: text/plain; name="Makefile"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename="Makefile"
OBJECTS =as_bug.o
CC =gcc
as_bug.com: $(OBJECTS) comfile.djl
ld -o as_bug.com -Tcomfile.djl $(OBJECTS) --oformat binary -M
.s.o:
$(CC) -c -o $*.o $*.s
---MOQ9905399804a11db13bd3a5e7e570a5b518e5a0f9e--
- Raw text -