Author Topic: Converting from Celsius to Fahrenheit  (Read 808 times)

AW

  • Member
  • *****
  • Posts: 2387
  • Let's Make ASM Great Again!
Re: Converting from Celsius to Fahrenheit
« Reply #15 on: April 29, 2019, 03:12:12 PM »
Actually is not yet time to open the bottle of champagne. Sorry for that.  :(
I don't believe in good luck, so I revisited the code. In the call to "num" edx is zeroed before the return. In the "C" part, all that is done after the return is push eax and call cf2. So edx is 0 (zero) within cf2 (unless you enter an absurdly high value for Celsius that makes the multiplication result over a dword). In conclusion, again, the reason for the crash is not the overflow.  :P
Sorry for this my troll friend.

jj2007

  • Member
  • *****
  • Posts: 9743
  • Assembler is fun ;-)
    • MasmBasic
Re: Converting from Celsius to Fahrenheit
« Reply #16 on: April 29, 2019, 05:23:47 PM »
In the call to "num" edx is zeroed before the return. In the "C" part, all that is done after the return is push eax and call cf2. So edx is 0 (zero)

Assuming that the C compiler leaves edx intact! Actually, I had not looked at the C code, and tested the asm code in isolation - my fault. So, if the C compiler kindly does not touch edx before calling c2f, then edx is still zero, and the cdq is not needed. Still, it would be very bad to rely on that behaviour (besides, mov edx, 0 is 5 bytes, cdq is only one). Furthermore, the cdq with idiv allows negative temperatures, the mov edx, 0 doesn't.

Here is complete code for use with Pelles C and MASM:
Code: [Select]
#include <stdio.h>
#pragma comment(linker, "c2f.obj /subsystem:console" )

extern int num();
extern double c2f(int n);

int main() {
    int number = num();
    // __asm int 3;
    double ret = c2f(number);
    printf("c2f returned %f\n", ret);
    _getch();
    return 0;
}
Code: [Select]
.486                                      ; create 32 bit code
.model flat, stdcall                      ; 32 bit memory model
option casemap :none                      ; case sensitive

include \Masm32\include\msvcrt.inc
includelib \Masm32\lib\msvcrt.lib
include \Masm32\include\Kernel32.inc
includelib \Masm32\lib\Kernel32.lib

.data
message db "The temperture in Fahrenheits: %d Reminder: %d", 10, 0
request db "Enter a temperature in Celsius: ", 0
celsius dd 0 ; 32-bits integer = 4 bytes
formatin db "%d", 0
txCrt db "msvcrt.dll", 0
txPrintf db "printf", 0
txScanf db "scanf", 0

.code
num proc C
  ;  Ask for an integer
  push offset request
  invoke LoadLibrary, offset txCrt
  invoke GetProcAddress, eax, offset txPrintf
  call dword ptr eax ; crt_printf
  add esp, 4    ; remove the parameter

  push offset celsius ; address of integer1, where the input is going to be stored (second parameter)
  push offset formatin ; arguments are right to left (first  parameter)
  invoke LoadLibrary, offset txCrt
  invoke GetProcAddress, eax, offset txScanf
  call dword ptr eax ; crt_printf
  add esp, 8    ; remove the parameters

  ; Move the value under the address integer1 to EAX
  ; mov edx, 0 wrong
  mov eax, celsius
  ret
num endp

c2f proc C arg
  mov eax, arg
  imul eax,9
  add eax,160
  mov ebx, 5
  ; INT 3
  cdq           ; allow negative
  idiv ebx      ; temperatures
  push eax
  fild dword ptr [esp]
  pop eax
  ret
c2f endp
END

TimoVJL

  • Member
  • ***
  • Posts: 475
Re: Converting from Celsius to Fahrenheit
« Reply #17 on: April 29, 2019, 06:24:54 PM »
Stupid question:
how that c2f function was defined in that exercise ?
should c2f function return int or double, or both ?

If celsius is an integer, result is also truncated to decimal, so is the fpu needed in that asm function ?

with extern int c2f(int n); C compiler can convert int to double for printf.
May the source be with you