i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?
From: August Derleth (see_at_sig.now)
Date: 01/20/04
- Next message: SenderX: "Re: Damn asm Dll and VB code..."
- Previous message: Amr Mostafa: "Re: what's the differ between lea and mov offset ?"
- Next in thread: Michael Brown: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Michael Brown: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Robert Wessel: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Phil Carmody: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 20 Jan 2004 22:54:21 +0000 (UTC)
When writing a small subroutine in i686 assembly for Linux (Red Hat 8.0,
kernel version 2.4.18-14), I came upon a bizarre problem: The div opcode
would cause my program to die after having failed to catch a floating
point exception. I replaced the div with an idiv, and nothing changed.
The problem stymied me completely until I chanced upon an assembly
source my C compiler (gcc 3.2) emitted: The idiv opcode in the emitted
assembly was preceded by a cdq (Convert Doubleword to Quadword) opcode,
which sign-extends eax into edx:eax. As the compiled C program ran
flawlessly, I dumped a cdq opcode into my own program. Problem solved.
But that's simply human-see, human-do. I want to understand why the idiv
opcode requires the cdq opcode, and whether this is a flaw in my
hardware (800 MHz AMD Duron), my OS, my assembler (nasm 0.98.34), or
anything else.
# For reference, here's a small shell script (Bourne-compatible) that
# will create two nasm assembly source files which produce two programs
# which demonstrate the problem and the solution, in addition to one
# Makefile. I'd be interested to know of any hardware/software
# combination that runs lose.asm without any problems, or that fails to
# run win.asm.
cat << CUT > lose.asm
;; A small program to divide two signed dwords
;; using the idiv opcode unsuccessfully
;; (without the cdq opcode).
section .text
global main
main: push ebp
mov ebp, esp
mov dword eax, 130
mov dword ecx, 5
idiv ecx ; We get floating point exception.
mov esp, ebp
pop ebp
ret ; We never return. Exception kills us.
;; Final value of eax is 136. Meaningful?
CUT
cat << CUT2 > win.asm
;; A small program to divide two signed dwords
;; using the idiv opcode successfully (via the
;; cdq opcode).
section .text
global main
main: push ebp
mov ebp, esp
mov dword eax, 130
mov dword ecx, 5
cdq ; sex edx:eax, eax
idiv ecx
mov esp, ebp
pop ebp
ret ; We return eax == 26
CUT2
cat << EOF > Makefile
cc = gcc
# Older Linux systems might prefer a.out as a format.
fmt = elf
win: win.o
$(cc) win.o -o win
win.o: win.asm
nasm -f $(fmt) win.asm
lose: lose.o
$(cc) lose.o -o lose
lose.o: lose.asm
nasm -f $(fmt) lose.asm
EOF
-- My address is yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz Note: Rot13 and convert spelled-out numbers to numerical equivalents.
- Next message: SenderX: "Re: Damn asm Dll and VB code..."
- Previous message: Amr Mostafa: "Re: what's the differ between lea and mov offset ?"
- Next in thread: Michael Brown: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Michael Brown: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Robert Wessel: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Reply: Phil Carmody: "Re: i686 (AMD Duron 800 MHz) idiv opcode needs cdq: Why?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|