Forum > Beginners
intel assembly code
tormods:
I have made the following function in assembly located in a separate unit (not an object). By debugging this code everything works fine until it reaches the first ret-instruction where it ends up with an exception with text: External: SIGSEGV. One other thing is when looking at the produced code the final ret instruction seems to be missing. This code is taken directly from one of my Delphi projects, where this code works fine. I belive that Delphi will substitute the END with a ret instruction automatically. Has this something to do with establishing the routine in a separate unit and the compiler can not generate the correct return address?
function __SkrUtilCheckInRange(Low,High,Val : integer) : boolean; assembler;
asm
cmp ecx,edx // check if Val > High
ja @@1 // return with FALSE
cmp ecx, eax // check if Val < Low
jb @@1 // return with FALSE
mov eax, 1 // return with TRUE
ret
@@1: xor eax, eax
end;
Tormods
Tomas Hajny:
Which compiler version and which options have you used for compiling this code? Can you post the generated assembly? It works in a simple test here performed with FPC 2.6.4 and using -Mdelphi (it wouldn't work correctly without -Mdelphi due to different size of "integer", because the code assumes 32-bit integers, but even then it shouldn't cause SIGSEGV, of course).
Laksen:
Did you compile it for x86_64 by chance?
I just compiled it for i386-win32 and it worked just fine
Edit: Crashes once in a while when the inline ret is there. Strange... I suppose it's related to the debugger and stack frame.
But anyway. There's no reason to have inline assembler in this day and age :)
This code is almost twice as fast as the assembler version:
--- Code: ---function __SkrUtilCheckInRange2(Low,High,Val : longword) : boolean;
begin
result := longword(val-low)<=longword(high-low);
end;
--- End code ---
ChrisF:
Using these assumptions will provoke a crash, indeed:
--- Code: ---{$mode objfpc}{$H+}
{$asmmode intel}
--- End code ---
While using the '{$mode delphi}' compatible mode seems to solve the problem.
Or you can remove the 'ret' instruction.
--- Code: ---function __SkrUtilCheckInRange(Low,High,Val : integer) : boolean; assembler;
asm
cmp ecx,edx // check if Val > High
ja @@1 // return with FALSE
cmp ecx, eax // check if Val < Low
jb @@1 // return with FALSE
mov eax, 1 // return with TRUE
jmp @@2
@@1: xor eax, eax
@@2:
end;
--- End code ---
Anyway, and according to my own experience, using previous Delphi assembly code inside FPC can rapidly turn into a nightmare (even in Delphi mode).
See this one, for instance: http://bugs.freepascal.org/view.php?id=24061, especially Jonas Maebe's answer.
tormods:
I have tried to check out the code the compiler produces, and found the cause why the code crashes:
New functioning code:
function __SkrUtilCheckInRange(Low,High,Val : integer) : boolean; assembler;
asm
cmp ecx,edx // check if Val > High
ja @@1 // return with FALSE
cmp ecx, eax // check if Val < Low
jb @@1 // return with FALSE
mov eax, 1 // return with TRUE
leave
ret
@@1: xor eax, eax
end;
The compiler produces the following code:
00552240 55 push ebp
00552241 89e5 mov ebp,esp
00552243 83ec04 sub esp,0x4
00552246 39d1 cmp ecx,edx
00552248 770b ja 0x552255 <__SKRUTILCHECKINRANGE+21>
0055224A 39c1 cmp ecx,eax
0055224C 7207 jb 0x552255 <__SKRUTILCHECKINRANGE+21>
0055224E b801000000 mov eax,0x1
00552253 c9 leave
00552254 c3 ret
00552255 31c0 xor eax,eax
00552257 c9 leave
00552258 c3 ret
Since the compiler produces the additional code:
push ebp
mov ebp,esp
sub esp,0x4
it needs to restore the esp and get back the epb and that is what the leave instruction does - analog code is :
mov esp, ebp
pop ebp
Why is this additional code added? it seems uneccessary. If an additional begin-end is used it produces a longer code:
skrutilities.pas:37 begin
00552240 55 push ebp
00552241 89e5 mov ebp,esp
00552243 83ec10 sub esp,0x10
00552246 8945fc mov DWORD PTR [ebp-0x4],eax
00552249 8955f8 mov DWORD PTR [ebp-0x8],edx
0055224C 894df4 mov DWORD PTR [ebp-0xc],ecx
0055224F 39d1 cmp ecx,edx
00552251 770b ja 0x55225e <__SKRUTILCHECKINRANGE+30>
00552253 39c1 cmp ecx,eax
00552255 7207 jb 0x55225e <__SKRUTILCHECKINRANGE+30>
00552257 b801000000 mov eax,0x1
0055225C c9 leave
0055225D c3 ret
0055225E 31c0 xor eax,eax
00552260 c9 leave
00552261 c3 ret
I tried to use delphi mode, this did not change the result.
I personally try to make effective assembly code and as such adding unecessary code is not a good idea.
By the way: it is possible to set the assmbly window in debugger to Intel notation rather than the A&T notation!
Tormods
Navigation
[0] Message Index
[#] Next page