Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2005-11

Bug with R+ and assembler functionsHi,

4 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Markus Kämmerer

Hi,

as you know we use FreePascal with our OpenXP Project (www.openxp.de/.com). We found, that after compiling our release version, an important function doesn't work anymore. After long search, I found, that compiling with R- instead of R+ is the reason. There is a bug in fpc. See the following code:

compiled with R+

# [904] zlen:=FindUmbruch(cont[offset],zlen); { in EDITOR.ASM } movl -20(%ebp),%edx
movl %ebx,%eax
movzwl -8(%ebp),%esi

> movl %esi,%ecx

cmpl $65500,%ecx
jbe .Lj1668
call FPC_RANGEERROR
.Lj1668:
leal 16(%eax,%esi,1),%eax
call EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT

compiled with R-

# [904] zlen:=FindUmbruch(cont[offset],zlen); { in EDITOR.ASM } movl -20(%ebp),%edx
movl %ebx,%eax
movzwl -8(%ebp),%ecx
leal 16(%eax,%ecx,1),%eax
call EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT

start of FindUmbruch:

DITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT:
.stabs "FINDUMBRUCH:f6",36,0,254,EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .stabs "DATA:rv35",64,0,254,0
.stabs "ZLEN:rp6",64,0,254,2
# Temps allocated between ebp-4 and ebp-4
.stabs "editor.pas",132,0,0,.Lf2
.Lf2:
.stabn 68,0,306,.Ll48 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .Ll48:
pushl %ebp
movl %esp,%ebp
subl $4,%esp
# Var data located in register
# Var zlen located in register
# Var $result 68,0,257,.Ll49 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .Ll49:
# [257] mov esi,data
movl %eax,%esi
.stabn 68,0,258,.Ll50 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .Ll50:
# [258] mov ebx,zlen
movl %edx,%ebx
.stabn 68,0,259,.Ll51 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT

Findumbruch awaits the "data" in esi. With the R+ version, the value is loaded to esi before range check. In the R- version the value is located in ecx and not been copied to esi, which is the bug.

You may test this bug with the openxp source
(ftp://www.openxp.de/openxp/openxp-4.0.7144.src.tar.bz2), file is editor.pas. R- can be changed in xpdefine.pas. Source compiled with -O1

If you need more information, I'll do as much as I can.

P.S. Pascal snippet of FindUmbruch

unction FindUmbruch(var data; zlen:integer):integer; assembler; {&uses ebx, esi}
{ r?ckw"rts von data[zlen] bis data[0] nach erster Umbruchstelle suchen } asm
mov esi,data
mov ebx,zlen
test ebx, ebx
jz @ufound
@floop:
mov al,[esi+ebx]
cmp al,' ' { ' ' -> unbedingter Umbruch } jz @ufound

cmp al,'-' { '-' -> Umbruch, falls alphanum. } jnz @testslash { Zeichen folgt: } mov al,[esi+ebx+1]
cmp al,'0' { '0'..'9' }
jb @fnext
cmp al,'9'
jbe @ufound
cmp al,'A' { 'A'..'Z' }
jb @fnext
cmp al,'Z'
jbe @ufound
cmp al,'a' { 'a'..'z' }
jb @fnext
cmp al,'z'
jbe @ufound
cmp al,'€' { '€'..'¥' }
jb @fnext
cmp al,'¥'
jbe @ufound
jmp @fnext

@testslash:
cmp ebx,1
ja @testslash2
mov ebx,0
jmp @ufound
@testslash2:
cmp al,'/' { '/' -> Umbruch, falls kein } jnz @fnext { Trennzeichen vorausgeht } cmp byte ptr [esi+ebx-1],' '
jz @fnext
cmp byte ptr [esi+ebx-1],'-'
jnz @ufound

  @fnext:
            dec   ebx
            jnz   @floop
  @ufound:
            mov   eax,ebx
{$IFDEF FPC }
end ['EAX', 'EBX', 'ESI'];
{$ELSE }
end;
{$ENDIF }

Reply by email

Jonas Maebe
to Markus Kämmerer
Markus Kämmerer wrote 11 lines
.stabn 68,0,257,.Ll49 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .Ll49: # [257] mov esi,data movl %eax,%esi .stabn 68,0,258,.Ll50 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT .Ll50: # [258] mov ebx,zlen movl %edx,%ebx .stabn 68,0,259,.Ll51 - EDITOR_FINDUMBRUCH$formal$LONGINT$$LONGINT Findumbruch awaits the "data" in esi.

No, in eax. "movl %eax, %esi" means "move the contents of eax into esi". This is AT&T assembler notation, not Intel.

With the R+ version, the value is loaded to esi before range check.

No, what is loaded in esi is "offset". The range check is to make sure that in the expression "cont[offset]", offset is not going past the end of the array.

In the R- version the value is located in ecx and not been copied to esi, which is the bug.

No. At least one problem is that in your assembler function, you use esi and ebx without saving/restoring them. ebx, esi and edi are callee-saved registers in the new default calling convention of FPC 2.0 (register calling), just like in C/C++.

Jonas

Reply by email

Markus Kämmerer
to Jonas Maebe
Jonas Maebe wrote
No, in eax. "movl %eax, %esi" means "move the contents of eax into esi". This is AT&T assembler notation, not Intel.

ops, i worked 10 years with intel assembler style, so i mixed this. sorry.

No. At least one problem is that in your assembler function, you use esi and ebx without saving/restoring them. ebx, esi and edi are callee-saved registers in the new default calling convention of FPC 2.0 (register calling), just like in C/C++.

Is there any docmentation about this? Must the eax register be saved, too? I thouht

end ['EAX', 'EBX', 'ESI'];

Is enough and tells the compiler, that these registers are changeing. In the current documentation i could not found information, about saving registers.

Markus

Reply by email

Peter Vreman
to Markus Kämmerer
Show quoted text 20 lines
Jonas Maebe wrote: > No, in eax. "movl %eax, %esi" means "move the contents of eax into esi". > This is AT&T assembler notation, not Intel. ops, i worked 10 years with intel assembler style, so i mixed this. sorry. > No. At least one problem is that in your assembler function, you use esi > and ebx without saving/restoring them. ebx, esi and edi are callee-saved > registers in the new default calling convention of FPC 2.0 (register > calling), just like in C/C++. Is there any docmentation about this? Must the eax register be saved, too? I thouht end ['EAX', 'EBX', 'ESI']; Is enough and tells the compiler, that these registers are changeing. In the current documentation i could not found information, about saving registers.

That works only for assembler blocks inside functions. For functions itself the standard calling conventions need to be followed. For i386 these are the same as delphi.

Reply by email