From: Wolfgang Kern on

Rod Pemberton answered:

> Okay, the splash screen comes up with a bunch of check boxes and then
> invalid instruction error:

> HEXTUTOR executed an invalid instruction in
> module HEXTUTOR.EXE at 0167:0041aaf2.
> Registers:
> EAX=00000001 CS=0167 EIP=0041aaf2 EFLGS=00010246
> EBX=00000000 SS=016f ESP=0054fca0 EBP=0054fce8
> ECX=00000000 DS=016f ESI=00008d40 FS=1097
> EDX=80005170 ES=016f EDI=0054fcd0 GS=0000
> Bytes at CS:EIP:
> 0f 45 15 40 30 40 00 0f 44 15 3c 30 40 00 51 0f

Yes, this is
CMOVNZ edx,[00403040h]
CMOVZ edx,[0040303ch]
PUSH ecx
....

> Stack dump:
> 0041aaa8 0041a3f3 0041a291 0054fcd0 00008d40 0054fce8
> 0054fccc 0054fd1c 00008d5c 00000000 00000000 bff7363b
> 00000b2c 0000000f 00000000 00000000

> 32-bit PM?

Yes, also if the 'disass.com' is started from DOS prompt to become
a PM32-TSR-module (once added for the few 32-bit DOS coders)

> cmovnz and/or cmovz ?

Yeah, and it uses SETcc/BT/BTC/BTS/BTR as well.

> They're unsupported by my CPU...

I see, and there might be more DX486 out there and still running ...

> Do you detect CPU via CPUID?

Not yet, but now I'm asked for, at least to mention minimal requirements.

Thanks a lot Rod, I'll change the readme.txt right now and check
the amount of work for 386/486 code versions.

__
wolfgang



From: Herbert Kleebauer on
Frank Kotler wrote:

> I haven't figured out why the "direct to binary" version isn't working.

Tried to do some testing but NASM is nothing but a disaster. Is it real
possible to write any working assembly program with it? Now I understand
why beginners prefer to use HLA. Maybe you can enlighten me:

If I use "nasm -l v1.lst -O999 -f bin -o v1 v1.asm" to assemble
this code:

========================================================================
org $08048000
dd $
offs equ $1000
aab equ $+offs
dd aab

I get an output file with the expected content:

00000 00 80 04 08 � 04 90 04 08 �

But in the list file:

1 org $08048000
2 00000000 [00000000] dd $
3 offs equ $1000
4 aab equ $+offs
5 00000004 [04100000] dd aab

the values given are without the org value which makes the listing
pretty useless. There also is no listing of all used labels or
have I to use some switch?

========================================================================

If i use this program

org $08048000
dd $
aab equ $+offs
dd aab
offs equ $1000

I would have expected the same output but get:

00000 00 80 04 08 � 04 10 00 00 �

The listing is the same, but with a missing []:

1 org $08048000
2 00000000 [00000000] dd $
3 aab equ $+offs
4 00000004 04100000 dd aab
5 offs equ $1000

========================================================================

And if I use:

org $08048000
dd $
aaa equ $+offs
dd aaa
offs equ $1000

I get:
v3.asm:3 error: expression syntax error
v3.asm:4 error: expression syntax error

Is this because aaa is an instruction name? Why does this prevent
aaa to be used as a label? And why isn't a proper error message used.
I use the label within a macro and always tried to understand what's
wrong with the macro.
From: Frank Kotler on
Herbert Kleebauer wrote:
> Frank Kotler wrote:
>
>
>>I haven't figured out why the "direct to binary" version isn't working.
>
>
> Tried to do some testing but NASM is nothing but a disaster.

Short answer, for now... I've never found Nasm's listing files to be the
least bit useful. In "-f bin" mode, you can ask for a map file:

[map all myprog.map]

In the source code (it's not a command line switch because it applies
only to binary output (normally, a map file would be a linker function).
Try that and see if you find it more useful.

Best,
Frank


From: Herbert Kleebauer on
Frank Kotler wrote:

> I haven't figured out why the "direct to binary" version isn't working.

Here a working version. It's ugly, but either NASM is missing some
important features or I don't understand how to proper use NASM.
The nop's are in again so I could do a binary compare with the
original binary.



; nasm -O999 -f bin -o myprog myprog.asm
;===========================================================================

%macro dc.b 2+
%ifidn %1,-
%else
%1 equ $+offs2
%endif
db %2
%endmacro

%macro dc.w 2+
%ifidn %1,-
%else
%1 equ $+offs2
%endif
dw %2
%endmacro

%macro dc.l 2+
%ifidn %1,-
%else
%1 equ $ + offs2
%endif
dd %2
%endmacro

;===========================================================================
; don't remove the following line and use offs directly
; this seems to be a bug in NASM
offs2 equ offs
;===========================================================================

@1 equ $08048000 ; virtual address of code start
@@1 equ 0 ; file byte address of code start

org @1
code_offset equ @@1
code_addr:
;===========================================================================

;--------------------------- ELF header -----------------------------------
dd $464c457f,$00010101,0,0,$00030002,1,main,$34,0,0,$00200034,2,0
dd 1,code_offset,code_addr,code_addr,code_filez,code_memsz,5,4096
dd 1,data_offset,data_addr,data_addr,data_filez,data_memsz,6,4096


;--------------------------- code ------------------------------------------
USE32

main: mov [stack_ptr], esp ; save initial stack pointer

; ******************** get socket handle ***************************
push 0 ; no protocol specified
push 1 ; 1: SOCK_STREAM (/usr/include/linux/net.h)
push 1 ; 1: AF_UNIX, AF_LOCAL (/usr/include/linux/socket.h)
mov ecx, esp ; pointer to parameter for "socket"
mov ebx, 1 ; "socket" (/usr/include/linux/net.h)
mov eax, 102 ; socketcall (/usr/include/asm/unistd.h)
int 80h
add esp, 3 * 4 ; free space for parameters
test eax, eax ; ERROR
js err

; my apologies for propagating this sloppiness.
; really should be "cmp eax, -4096" (or -4095?)
; won't happen here, but we *could* get a
; valid return over 2G! - fbk

mov [x_handle], eax

; ********** connect socket to /tmp/.X11-unix/X0" ******************
push sockaddr_un_l
push sockaddr_un ; (/usr/include/linux/un.h)
push dword [x_handle] ; socket handle
mov ecx, esp ; pointer to parameter for "connect"
mov ebx, 3 ; "connect" (/usr/include/linux/net.h)
mov eax, 102 ; socketcall (/usr/include/asm/unistd.h)
int 80h
add esp, 3 * 4 ; free space for parameters
test eax, eax ; ERROR
js err

; *************** make socket read non blocking *******************
mov ebx, [x_handle] ; socket handle
mov ecx, 3 ; F_GETFL (/usr/include/asm/fcntl.h)
mov eax, 55 ; fcntl (/usr/include/asm/unistd.h)
int 80h
test eax, eax ; ERROR
js err
mov ebx, [x_handle] ; socket handle
mov ecx, 4 ; F_SETFL (/usr/include/asm/fcntl.h)
mov edx, eax
or edx, 800h ; O_NONBLOCK (/usr/include/asm/fcntl.h)
mov eax, 55 ; fcntl (/usr/include/asm/unistd.h)
int 80h
test eax, eax ; ERROR
js err

; ******************* send connect message *************************
mov eax, send1 ; pointer to connect message
mov edx, send1l

call get_xauth ; try to read .Xauthority
jc _11 ; no success, let's try without auth.

mov [send1+6], bx ; insert name length
mov [send1+8], si ; insert data length

call x_send ; send header

mov eax, ecx ; pointer to name
lea edx, [ebx + 3] ; pad to a multiple of 4
and edx, -4
call x_send ; send name

mov eax, ebp ; pointer to data
lea edx, [esi + 3] ; pad to a multiple of 4
and edx, -4
_11: call x_send ; send data

xor ebp, ebp ; number of total bytes read
mov esi, buf2 ; pointer to buffer for next read
mov edi, buf2l ; max. bytes to read

.10: mov eax, esi
mov edx, edi
call x_receive_raw
jz .10 ; but we need a reply

cmp byte [buf2], 1 ; success
jne err ; something went wrong

add ebp, eax ; total read bytes
add esi, eax ; pointer to buffer for next read
sub edi, eax ; max. bytes to read
cmp ebp, 8 ; at least 8 bytes read?
jc .10 ; no, get more

movzx ebx, word [buf2 + 6] ; additional data in 4 bytes
lea ebx, [ebx * 4 + 8] ; total size in bytes
cmp ebp, ebx ; all read
jc .10 ; no, get more

; ******************* calculate id's *******************************
mov esi, buf2
mov eax, [esi + 0Ch] ; resource_id_base

mov edx, [esi + 10h] ; resource_id_mask
mov ecx, edx
neg ecx
and edx, ecx ; resource_id_incr

mov [s2a], eax ; wid for CreateWindow
mov [s3a], eax ; wid for MapWindow
mov [s4a], eax ; wid for CreateDC
mov [s5a], eax ; wid for CreateDC
mov [s6a], eax ; wid for SetInputFocus

add eax, edx ; next id
mov [s4b], eax ; cid for CreateDC
mov [s5b], eax ; cid for CreateDC

add eax, edx ; next id ; lint!!!

; mov [resource_id_next], eax
; mov [resource_id_incr], edx

; ******************* get root window id ***************************
movzx eax, word [esi + 18h] ; length of vendor string
add eax, 28h + 3 ; const header length + round vendor length
and al, -4 ; round to 4 bytes

movzx edx, byte [esi + 1Dh] ; number of FORMATs
shl edx, 3 ; 8 byte for each FORMAT entry
add edx, eax ; offset to root WINDOW id

mov eax, [esi + edx] ; root window
mov [s2b], eax ; CreateWindow needs root window id

mov eax, [esi + edx + 20] ; width/height of root window
mov [s2x], eax ; create window full size

sub eax, (200 << 16) + 320
shr eax, 1
and eax, 0FFFF7FFFh
mov [s5x], eax ; center drawing

; ******************* send CreatWindow request *********************
mov eax, send2
mov edx, send2l
call x_send
call x_receive
jz .20 ; no message is a good message
cmp byte [eax], 0 ; error message
je ende

; ******************* send MapWindow request ***********************
.20: mov eax, send3
mov edx, send3l
call x_send
call x_receive
jz .30 ; no message is a good message
cmp byte [eax], 0 ; error message
je ende

; ******************* send CreatDC request *************************
.30: mov eax, send4
mov edx, send4l
call x_send
call x_receive
jz .40 ; no message is a good message
cmp byte [eax], 0 ; error message
je ende

; ******************* send SetInputFocust *************************
.40: mov eax, send6
mov edx, send6l
call x_send
call x_receive
jz .60 ; no message is a good message
cmp byte [eax], 0 ; error message
je ende

.60: call init_color ; init 64 VGA colors

; ******************** main loop ***************************
.50: call annie ; generate next picture
call display
call x_receive
jz .50 ; no message is a good message

cmp byte [eax], 0 ; error message
je err
cmp byte [eax], 2 ; key press
je ende
cmp byte [eax], 4 ; button press
jne .50
err:
ende: mov ebx, 0 ; return code
mov eax, 1 ; exit
int 80h

;------------------------------------------
display:
mov esi, screen
mov ecx, 20 ; we use 20 parts to make each less than 16k
..10
mov eax, send5
mov edx, send5l
call x_send
mov eax, esi
mov edx, 320 * 10 * 4 ; size of one part
call x_send
add word [s5y], 10 ; update y pos for next part
add esi, 320*10*4 ; update source pointer for next part
loop .10
sub word [s5y], 20*10 ; restore original y position
ret
;-----------------------------------------

; ********* Annie's code to draw a heart ****************
annie: pusha
xor ebx, ebx

.10: inc dword [annie1]
mov ecx, 320 * 200
xor edi, edi
.20: mov eax, edi ; byte pos in screen
xor edx, edx
mov ebx, 320 ; 320 lines
div ebx ; eax: line 0-199 edx: column 0-319
sub eax, 120 ; center y=120 (-120 .. +79)
sub edx, 160 ; x=160 (-160 .. +159)
jg .30
neg edx ; symmetric in x (0 .. 160)
.30: mov ebx, eax
imul ebx, ebx ; ebx = x*x
add eax, edx ; eax = x*x+y
imul eax ; eax = (x*x+y)**2 mod 2*16
add ebx, eax
jz .40
xor edx, edx
mov eax, 600000
div ebx
.40: add eax, [annie1] ; change color
shr al, 2
movzx eax, al
mov eax, [color+ eax * 4]
mov [screen + edi * 4], eax
inc edi
loop .20

popa
nop
ret

; ****************** initialize 64 VGA colors *********************
init_color:
pusha
mov esi, color
mov eax, 0 ; sic
mov ecx, 64
_01: mov [esi], eax
add esi, 4
add al, 10h
add ax, 800h
add eax, 40000h
loop _01
popa
nop
ret

;**********************************************************
;******** read cookie from $home/.Xauthority **************
;**********************************************************
; *
; input: stack_ptr: original sp at program start *
; output: C=0: cookie found in $home/.Xauthority *
; r2: pointer to protocol name *
; r3: length of protocol name *
; r4: pointer to protocol data *
; r5: length of protocol data *
; C=1: nothing found *
; r2/r3/r4/r5 undefined *
; *
; typedef struct xauth { *
; unsigned short family; *
; unsigned short address_length; *
; char *address; *
; unsigned short number_length; *
; char *number; *
; unsigned short name_length; *
; char *name; *
; unsigned short data_length; *
; char *data; *
; } Xauth; *
;**********************************************************

get_xauth:
push eax
push edx
push edi

mov edi, [stack_ptr] ; original stack pointer at program start
mov eax, [edi] ; number of arguments
lea edi, [edi + eax * 4 + 8] ; skip arguments + trailing null pointer

.20: mov esi, [edi] ; pointer to next env variable
add edi, 4
test esi, esi ; no more env variables
jz .notfound
cmp dword [esi], 'HOME' ; HOME found?
jne .20 ; no, try next
cmp byte [esi + 4], '=' ; HOME= found?
jne .20 ; no, try next
add esi, 5 ; start of HOME path
or ecx, -1
.30: inc ecx ; count length of HOME path
cmp byte [esi + ecx], 0
jne .30

or ecx, ecx ; at least one char long?
jz .notfound ; no, HOME is empty
cmp ecx, 256 ; more than 256 charcters
ja .notfound ; somebody tries a buffer overflow
mov edi, fname ; buffer for filename
rep movsb ; copy HOME path
mov eax, '/.Xa' ; 'aX./' ; add .Xauthority
stosd
mov eax, 'utho' ; 'ohtu'
stosd
mov eax, 'rity' ; 'ytir'
stosd
mov byte [edi], 0 ; and a trailing 0

mov ebx, fname
xor ecx, ecx ; readonly
mov eax, 5 ; open
int 80h

test eax, eax ; file open error?
js .notfound ; yes

mov ebx, eax ; file handle
mov ecx, buf2
mov edx, buf2l ; read 1024 byte
mov eax, 3 ; read
int 80h

cmp eax, buf2l
jnc err ; .Xauthority >= 1024 byte
mov ebp, eax ; bytes read

mov eax, 6 ; close
int 80h

test ebp, ebp ; file empty
jz .notfound

mov esi, buf2
add ebp, esi ; end of read data
xor eax, eax

.60: lodsw ; family
dec ax
jz .40 ; 1=FamilyLocal

mov ecx, 4 ; skip entry
.50: lodsw
ror ax, 8 ; big -> little endian
add esi, eax
loop .50
cmp esi, ebp ; more data
jc .60 ; try next entry

..notfound:
stc
jmp _70

.40: mov ecx, 2
mov ebx, ecx
.41: lodsw
ror ax, 8
add esi, eax ; skip address/number
loop .41

.42: lodsw
ror ax, 8
mov ecx, esi
mov ebx, eax
add esi, ebx

lodsw
ror ax, 8
mov ebp, esi
mov esi, eax
clc
_70: pop edi
pop edx
pop eax
ret

;**********************************************************
;******** send message to X server **************
;**********************************************************
; input: eax: pointer to message *
; edx: length of message *
;**********************************************************
x_send: pusha
mov ebp, eax ; pointer to next byte of message
mov esi, edx ; remaining bytes to send

.20: push 0 ; flags
push esi ; length
push ebp ; pointer to data
push dword [x_handle] ; socket handle
mov ecx, esp ; pointer to parameter for "send"
mov ebx, 9 ; "send" (/usr/include/linux/net.h)
mov eax, 102 ; socketcall (/usr/include/asm/unistd.h)
int 80h
add esp, 4*4 ; free space for parameters

cmp eax, -11 ; EAGAIN:
je .20 ; message couldn't be sent, try again

test eax, eax ; ERROR
js err

sub esi, eax ; remaining bytes to send
jz .30 ; nothing, all sent
add ebp, eax ; pointer to remaining message
jmp .20 ; send rest of message

.30: popa
nop
ret

;**********************************************************
;******** receive ONE message from X server **********
;**********************************************************
; input: none *
; output: Z=1: no complete message available *
; eax/edx undefined *
; Z=0: eax: pointer to message data *
; edx: size of data *
;**********************************************************
x_receive:
push ecx
push esi
push edi
_00: mov eax, [buf2_rest] ; still something in read buffer?
cmp eax, 32 ; a message has at least 32 bytes
jnc .10 ; maybe it is a complete message

.30: mov esi, [buf2_ptr] ; start of message
mov edi, buf2 ; start of buffer
mov [buf2_ptr], edi ; we copy message to top of buffer
cmp edi, esi ; already at top of buffer
je .50 ; then nothing to copy
or eax, eax ; nothing in buffer
jz .50 ; then also nothing to copy
mov ecx, eax ; copy to top of buffer
rep movsb

.50: mov edx, buf2l ; let's try to get some more data
sub edx, eax ; not more bytes than space is left in the buf
lea eax, [buf2 + eax] ; append it here
call x_receive_raw
jnz .20 ; we could read something
jmp _100 ; return with Z=1

.20: add [buf2_rest], eax ; now we have a few more bytes in the buffer
jmp _00 ; let's try again

.10: mov esi, [buf2_ptr] ; let's test if it is a complete meesage
cmp byte [esi], 34
ja err ; the last known message is nr 34
mov edx, 32
; cmp byte [esi], 0 ; error message
; je .40
cmp byte [esi], 1 ; reply message
jne .40 ; event message is always 32 byte
add edx, [esi + 12] ; + additional data for reply
add edx, [esi + 12] ; + additional data for reply
add edx, [esi + 12] ; + additional data for reply
add edx, [esi + 12] ; + additional data for reply
cmp eax, edx ; complete reply in buffer
jc .30 ; no, let's try to get more
.40: mov eax, esi ; pointer to data
sub [buf2_rest], edx ; new rest
add [buf2_ptr], edx ; pointer to next data; clear Z flag
_100: pop edi
pop esi
pop ecx
ret

;**********************************************************
;******** read data from X server **********
;**********************************************************
; input: eax: pointer to read buffer *
; edx: size of buffer *
; output: Z=1: nothing to read *
; Z=0: eax bytes read *
;**********************************************************
x_receive_raw:
push ecx
push ebx

push 0 ; flags
push edx ; bytes to read
push eax ; pointer to buffer
push dword [x_handle] ; socket handle
mov ecx, esp ; pointer to parameter for "recv"
mov ebx, 10 ; "recv" (/usr/include/linux/net.h)
mov eax, 102 ; socketcall (/usr/include/asm/unistd.h)
int 80h
add esp, 4 * 4 ; free space for parameters
pop ebx
pop ecx
cmp eax, -11 ; EAGAIN: no message available -> Z=1
je .10
test eax, eax ; <0: ERROR 0: NULL message -> Z=1
js err
.10: ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;--------------------------- constant data ---------------------------------
; (note that we're in .text, not .rdata)

align 4

sockaddr_un:
dw 1 ; 1: AF_UNIX, AF_LOCAL (/usr/include/linux/socket.h)
db "/tmp/.X11-unix/X0"
sockaddr_un_l equ $ - sockaddr_un


;---------------------------------------------------------------------------
;---------------------------------------------------------------------------

;===========================================================================
; end of code and constant data section
;===========================================================================

align 4
@2 equ @1 + ($-code_addr);virtual address of end of code
@@2 equ @2-@1 ; file byte address of end of code
code_filez equ @@2-@@1
code_memsz equ @2-@1
@3 equ (@2+4095) / 4096 * 4096+(@@2 % 4096)
; virtual address of data start
@@3 equ @@2 ; file byte address of data start
offs equ @3-@2 ; diff between NASM $ and virt. addr. data section

data_offset equ @@3
data_addr equ $+offs2


;===========================================================================
; start of data section
;
; you MUST NOT use db/dw/dd to define data, use dc.b/dc.w/dc.l instead
;===========================================================================


;--------------------------- initialized data ------------------------------
dc.l buf2_ptr, buf2
dc.l buf2_rest, 0

; Connection Setup
dc.b send1 , $6c,0 ; LSB first
dc.w - , 11,0 ; major/minor version
dc.w - , 0,0 ; length of protocol name/data
dc.w - , 0 ; unused
send1l equ $+offs2 - send1

; Create Window
dc.b send2 , 1 ; opcode for Create Window
dc.b - , 0 ; depth from parent
dc.w - , send2l/4; request length
dc.l s2a , 0 ; wid (has to be calculated)
dc.l s2b , 0 ; parent (has to be calculated)
dc.w - , 0 ; x
dc.w - , 0 ; y
dc.w s2x , 640 ; width
dc.w s2y , 400 ; heigth
dc.w - , 0 ; border-width
dc.w - , 0 ; class: CopyFromParent
dc.l - , 0 ; visual: CopyFromParent
dc.l - , 0A02h ; value-mask: background-pixel 2
; + override-redirect 200
; + event-mask 800
dc.l - , 0 ; background: black
dc.b - , 1 ; override-redirect = true
dc.b - , 0,0,0 ; pad
dc.l - , 5 ; event_mask: KeyPress 1
; +ButtenPress 4
; +PointerMotion 40
send2l equ (($+offs2 - send2)+3) & 0fffffffch

; Map Window
dc.b send3 , 8 ; opcode for Map Window
dc.b - , 0 ; unused
dc.w - , send3l/4; request length
dc.l s3a , 0 ; wid (has to be calculated)
send3l equ $+offs2 - send3

; Create GC
dc.b send4 , 55 ; opcode for CreateGC
dc.b - , 0 ; unused
dc.w - , send4l/4; request length
dc.l s4b , 0 ; cid (has to be calculated)
dc.l s4a , 0 ; wid (has to be calculated)
dc.l - , 1+4+8 ; function+foreground+background
dc.l - , 3 ; function=copy
dc.l - , 0ffffffh ; foreground: white
dc.l - , 0080ffh ; background: light blue
send4l equ $+offs - send4

; Put Image
dc.b send5 , 72 ; opcode for PutImage
dc.b - , 2 ; ZPixmap
dc.w - , send5l/4 + 320*10*4/4 ; request length
dc.l s5a , 0 ; wid (has to be calculated)
dc.l s5b , 0 ; cid (has to be calculated)
dc.w - , 320 ; width
dc.w - , 200/20 ; height
dc.w s5x , 0 ; dest-x
dc.w s5y , 0 ; dest-y
dc.b - , 0 ; left-pad
dc.b - , 24 ; depth
dc.w - , 0 ; unused
send5l equ $+offs2 - send5

; Set Input Focus
dc.b send6 , 42 ; opcode for SetInputFocus
dc.b - , 0 ; revert-to None
dc.w - , send6l/4; request length
dc.l s6a , 0 ; wid (has to be calculated)
dc.l - , 0 ; timestamp CurrentTime
send6l equ $+offs2 - send6


;===========================================================================

@4 equ @3 + ($+offs2)-data_addr ; virtual address of end of data
@@4 equ data_offset + ($+offs2)-data_addr ;file byte addr.of e.o.d

section .bss
resb offs2 ; now NASM $ and virt. address are synchron again
@5 equ $ ; virtul address of start of unitialized data
;===========================================================================

;--------------------------- uninitialized data ----------------------------

screen: resd 320*200 ; bitmap

stack_ptr: resd 1
x_handle: resd 1
annie1: resd 1
color: resd 64
fname: resb 256+32
buf2: resb 1024
buf2l equ $ - buf2

;---------------------------------------------------------------------------

;===========================================================================
@6 equ $ ; virtual address of end of unitialzed data
data_filez equ @@4-@@2
data_memsz equ @4-@3 + @6-@5
;===========================================================================
From: T.M. Sommers on
Herbert Kleebauer wrote:
> "T.M. Sommers" wrote:
>>Rod Pemberton wrote:
>
>>>>>case 0x05: {la[--j] = la[j] / la[j+1]; break;}
>>>>
>>>I.e., assuming LALR(1) and applying precedence, the above is:
>>>case 0x05:
>>>{
>>> --j;
>>> la[j] = la[j] / la[j+1];
>>> break;
>>>}
>>>
>>>It appears that DJGPP (GCC) works properly while OpenWatcom v1.3 fails. I'd
>>>guess that most K&R style compilers work.
>>
>>The origial line invokes undefined behavior; anything the
>>compiler does is "proper".
>
> Then you have a very bizarre definition of "proper".

No, you do. The standard allows a compiler to do anything it
wants when it encounters undefined behavior. There is no way to
say that one compiler is right and another wrong.

> It isn't a
> problem when the behaviour for such a construct is undefined in the
> C specification. The problem arises when an implementation of the C
> specification defines the behaviour for this construct.

The problem is that the two compilers are allowed to do different
things, and no one can say one is right and the other wrong.

> If the
> behaviour would still be undefined in the implementation, then
> the compiler would emit an error message an stop if it encounter
> this construct. It would be also no problem if all compilers would
> implement the same behaviour (and so extend the C specification
> in a consistent manner).

Sure, the standard could be changed, but today you have to deal
with it as it is.

> But how should you get aware of the
> problem with a construct like "la[--j] = la[j] / la[j+1];" if
> it exactly does what you suppose it to do with the compiler you
> use?

By learning the language properly.

--
Thomas M. Sommers -- tms(a)nj.net -- AB2SB


First  |  Prev  |  Next  |  Last
Pages: 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Prev: masm linking from console
Next: NASM HelloWorld - DOS