The MASM Forum

General => The Campus => Topic started by: RKC on April 29, 2019, 06:14:14 AM

Title: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 06:14:14 AM
I am tasked at writing a program in C that uses external modules from from a .asm file. I do not have a background in assembly, mainly cpp. However, I managed to get so far into my program using a book by kip Irvine, YouTube videos, etc. All of my code works up to the c2f function, which is where I start having the problems. The entire code is attached in the two separate files, but a code snippet from the .asm file c2f: is below. Basically as soon as it gets to the mov ebx, 5 it calls a segmentation fault core dumped. I tried using the edx register and this causes a floating point core dumped in my terminal. I've literally exhausted all options and I ran across this forum by chance in my search for an answer. Can somebody please help me, rubber ducky hasn't helped.

c2f:
  mov eax, [esp+4]
  imul eax,9
  add eax,160
  mov ebx, 5
  div ebx

  ret

Edit: And I know it would be nice to just have the fix for this, but the why is what's driving me nuts. Even though this is just one assignment and the class is not over assembly, I would like to understand why. I know that when you divide by something the overflow goes into edx, but I don't know why it's causing the errors that it causes. Any help or suggestions is appreciated.
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 on April 29, 2019, 06:38:13 AM
floats are returned in ST0 not in eax.
Title: Re: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 06:42:45 AM
If floats are returned in STO, then how would the ret function work?

c2f:
  mov eax, [esp+4]
  imul eax,9
  add eax,160
  ;mov ebx, 5
  ;div ebx

  ret

Noticed the two lines commented out, if I type in 20 in the function, it returns 340. I know that the function is getting that far so the error is in mov ebx, 5 and div ebx.
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 on April 29, 2019, 06:49:55 AM
It is NOT an IF, they do indeed return in ST0. Don't doubt what people here tells you unless you can present evidence.

So, what you have to do is convert the integer to float before the RET. Isn't it obvious?
If you don't want to do it, make the C function wait for an integer.

Title: Re: Converting from Celsius to Fahrenheit
Post by: jj2007 on April 29, 2019, 06:54:46 AM
You get an exception with div ebx because edx is not zero. Use the cdq instruction:
c2f:
  mov eax, [esp+4]
  imul eax,9
  add eax,160
  mov ebx, 5
  cdq
  div ebx
  retn 4


Btw which assember are you using? It's definitely not MASM 8)
Title: Re: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 06:59:00 AM
Quote from: AW on April 29, 2019, 06:49:55 AM
It is NOT an IF, they do indeed return in ST0. Don't doubt what people here tells you unless you can present evidence.

So, what you have to do is convert the integer to float before the RET. Isn't it obvious?
If you don't want to do it, make the C function wait for an integer.

Ok first thing,  I was only asking out of clarification because I was only handed a crappy little one liner that isn't blatantly obvious to somebody that hasn't seen this before this week. Second off, no reason to be such a prick about it. While some things may seem nontrivial to you, it may not be so to somebody that just got forced to learn an abundance of the language in a short amount of time. I simply was asking for clarification, I even posted the snippet with what I had commented out and what I had returned up until that point to further clarify where I had gotten. If that is how you react to a clarity question with an explanation of debugging I sincerely hope that you are not a supervisor anywhere because I would really hate to work for your company, or with you for that matter. While I appreciate your reply, I wasn't doubting what you were telling me, maybe the response came off as such, I don't know so I apologize if it did.
Title: Re: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 07:01:40 AM
Quote from: jj2007 on April 29, 2019, 06:54:46 AM
You get an exception with div ebx because edx is not zero. Use the cdq instruction:
c2f:
  mov eax, [esp+4]
  imul eax,9
  add eax,160
  mov ebx, 5
  cdq
  div ebx
  retn 4


Btw which assember are you using? It's definitely not MASM 8)

Thanks for the reply bud! I'll have to look up cdq. I thought it was MASM from what I had looked up. I am taking a systems programming class so I am doing all of this in a dual boot ubuntu system. I'm running straight off the terminal using makefile with my folder. We had been doing nothing but C programming up until this past week. I thought it was assembly for x86 processors  :badgrin: oops! Honestly most of my assembly language experience is in MIPS.

I'm still getting a core dumped, but I'm looking into it. Thanks for pointing me in the right direction!
Title: Re: Converting from Celsius to Fahrenheit
Post by: jj2007 on April 29, 2019, 07:11:54 AM
cdq sign-extends eax to edx: if eax is positive, edx will be set to zero, if eax is negative, edx will be -1.

Here are two variants of your code, both return the result in eax and in ST(0):

c2f:
  mov eax, [esp+4]
  imul eax,9
  add eax,160
  mov ebx, 5
  cdq
  div ebx
  push eax
  fild dword ptr [esp]
  pop eax
  retn 4

c2fx:
  fild dword ptr [esp+4]
  push 9
  fimul dword ptr [esp] ; mul 9
  pop edx
  push 160
  fiadd dword ptr [esp] ; add 160
  pop edx
  push 5
  fidiv dword ptr [esp] ; div 5
  fist dword ptr [esp]
  pop eax
  retn 4


Quote from: RKC on April 29, 2019, 06:59:00 AMno reason to be such a prick about it.

José doesn't need a reason :P
Title: Re: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 07:16:31 AM
Thank you! I'm actually at a tossup between this or MIPS. I'll admit it's rather nice not having to type a $ all the time hahaha! I found some good documentation on cdq but this helps a lot.

I see the problem, it's actually NASM, not sure if that makes a massive difference but the ptr will not work in it.
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 on April 29, 2019, 07:28:14 AM
I attach a Visual Studio project with the asm converted to MASM.
The reason for the crash is not the CDQ, I am not using any CDQ, JJ is still learning the basics.

If you want float precision you will have to convert as I told you before. Otherwise the C will round it.

NASM is a free form assembly language.
Title: Re: Converting from Celsius to Fahrenheit
Post by: RKC on April 29, 2019, 07:33:42 AM
Quote from: AW on April 29, 2019, 07:28:14 AM
I attach a Visual Studio project with the asm converted to MASM.
The reason for the crash is not the CDQ, I am not using any CDQ, JJ is still learning the basics.

If you want float precision you will have to convert as I told you before. Otherwise the C will round it.

NASM is a free form assembly language.

Thank you both, I really appreciate the time that y'all spent helping me. I've gotten past one barrier so far and onto another one in my own code. It is hard to know what C will and won't do with code sometimes, I noticed what you told me was exactly right and I appreciate it, just working on converting it now.
Title: Re: Converting from Celsius to Fahrenheit
Post by: jj2007 on April 29, 2019, 07:56:51 AM
Quote from: AW on April 29, 2019, 07:28:14 AMThe reason for the crash is not the CDQ, I am not using any CDQ, JJ is still learning the basics.

I know I shouldn't feed the troll, but for RKC: Without the cdq, the code will crash at the div, with exception C0000095 alias INTEGER_OVERFLOW. It may not crash if by accident edx is between 0 and 4. I've debugged the code, I know what I'm doing.

Btw, since temperatures can be negative, the correct way of dividing is using idiv:
  mov ebx, 5
  cdq
  idiv ebx
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 on April 29, 2019, 08:19:38 AM
Explain how it will "crash". Do you know how DIV works?

DIV : Unsigned divide EDX:EAX by r/m32, with result stored in EAX ← Quotient, EDX ← Remainder.

What can happen is a wrong result but how will it crash? Probably you must make a proof in Basic.  :badgrin:
Title: Re: Converting from Celsius to Fahrenheit
Post by: jj2007 on April 29, 2019, 08:29:39 AM
When you are short of arguments, you start insulting people, José.

include \masm32\include\masm32rt.inc

.code
start:
  mov eax, 610 ; e.g. in RKC's example for C=50: 50*9+160
  mov edx, 5 ; any value except 0...4 will crash
  mov ebx, 5
  div ebx ; exception C0000095 alias INTEGER_OVERFLOW
  inkey str$(eax)
  exit
end start


You may google for "If the quotient is too large for the designated register" (with quotes).
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 on April 29, 2019, 08:55:32 AM
Very good, it is the first time I have to concede to you! Time to open that bottle of champagne you have in the fridge for so long.  :t
Title: Re: Converting from Celsius to Fahrenheit
Post by: aw27 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.
Title: Re: Converting from Celsius to Fahrenheit
Post by: jj2007 on April 29, 2019, 05:23:47 PM
Quote from: AW on April 29, 2019, 03:12:12 PMIn 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:
#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;
}

.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
Title: Re: Converting from Celsius to Fahrenheit
Post by: TimoVJL 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.