#include <iostream>
using namespace std;
int GCD(int, int);
int main()
{
int x, y;
cout << "Enter two integers\n1: ";
cin >> x;
cout << "2: ";
cin >> y;
cout << "The greatest common denominator of these numbers is " << GCD(x, y) << endl;
system("PAUSE");
return 0;
}
int GCD(int x, int y)
{
int temp;
if(x > y)
if(x % y == 0)
return y;
if(y > x)
if(y % x == 0)
return x;
while (x > 0)
{
temp = x;
x = y % x;
y = temp;
}
}
Why does this code work?
There must be something going on with the compiler that I don''t know about.
If you notice after the while loop I do not return a value, but for some reason it does return the correct value. I''m very confused.
Here is the dissassembly of your GCD function.
If you notice, the compiler has assumed what should be returned, and it added that code for you.
I was wrong, read CWizards second post, and my post after that.
[edited by - yummy_potatoes on March 2, 2003 12:39:55 PM]
[edited by - yummy_potatoes on March 2, 2003 12:49:48 PM]
--- C:\Documents and Settings\Sysop\Desktop\Test\test.cpp -----------------------------------------------------------------15:16: int GCD(int x, int y)17: {00401920 push ebp00401921 mov ebp,esp00401923 sub esp,44h00401926 push ebx00401927 push esi00401928 push edi00401929 lea edi,[ebp-44h]0040192C mov ecx,11h00401931 mov eax,0CCCCCCCCh00401936 rep stos dword ptr [edi]18: int temp;19: if(x > y)00401938 mov eax,dword ptr [ebp+8]0040193B cmp eax,dword ptr [ebp+0Ch]0040193E jle GCD+30h (00401950)20: if(x % y == 0)00401940 mov eax,dword ptr [ebp+8]00401943 cdq00401944 idiv eax,dword ptr [ebp+0Ch]00401947 test edx,edx00401949 jne GCD+30h (00401950)21: return y;0040194B mov eax,dword ptr [ebp+0Ch]0040194E jmp GCD+66h (00401986)22: if(y > x)00401950 mov ecx,dword ptr [ebp+0Ch]00401953 cmp ecx,dword ptr [ebp+8]00401956 jle GCD+48h (00401968)23: if(y % x == 0)00401958 mov eax,dword ptr [ebp+0Ch]0040195B cdq0040195C idiv eax,dword ptr [ebp+8]0040195F test edx,edx00401961 jne GCD+48h (00401968)24: return x;00401963 mov eax,dword ptr [ebp+8]00401966 jmp GCD+66h (00401986)25:26: while (x > 0)00401968 cmp dword ptr [ebp+8],00040196C jle GCD+66h (00401986)27: {28: temp = x;0040196E mov edx,dword ptr [ebp+8]00401971 mov dword ptr [ebp-4],edx29: x = y % x;00401974 mov eax,dword ptr [ebp+0Ch]00401977 cdq00401978 idiv eax,dword ptr [ebp+8]0040197B mov dword ptr [ebp+8],edx30: y = temp;0040197E mov eax,dword ptr [ebp-4]00401981 mov dword ptr [ebp+0Ch],eax31: }00401984 jmp GCD+48h (00401968)32: }00401986 pop edi00401987 pop esi00401988 pop ebx00401989 mov esp,ebp0040198B pop ebp0040198C ret
If you notice, the compiler has assumed what should be returned, and it added that code for you.
I was wrong, read CWizards second post, and my post after that.
[edited by - yummy_potatoes on March 2, 2003 12:39:55 PM]
[edited by - yummy_potatoes on March 2, 2003 12:49:48 PM]
I think this does not work, it just happen by chance to behave as expected. You should have a warning about that not all control paths return a value. This will cause the function to return an undefined value in those cases. In this case, probably whatever is in eax, which might be just what you intend to return. This is pure speculation, though.
quote:Original post by yummy_potatoesNo, i do not notice that. The value that the function returns is the value that is in eax when it comes back from the call. I can''t see that the compiler has inserted anything like that.
If you notice, the compiler has assumed what should be returned, and it added that code for you.
Ahh, yes. It would indeed return whatever is in EAX, because that is the standard register for that kind of thing. I just now remembered that in MASM32, you get your return value from EAX after invoking a function.
What exactly is the EAX register for, and why do they use it to store temporary values and the return value.
I tried looking it up and I found that AX was the incremental register though I didn''t see an EAX for. Also I stepped through the dissasembly and I saw that every temp variable the compiler used was stored in EAX.
Any incite would be helpfull.
I tried looking it up and I found that AX was the incremental register though I didn''t see an EAX for. Also I stepped through the dissasembly and I saw that every temp variable the compiler used was stored in EAX.
Any incite would be helpfull.
quote:Original post by ph33r
What exactly is the EAX register for, and why do they use it to store temporary values and the return value.
EAX is merely an extended register. AX is a 16-bit register used mostly with old DOS programs. EAX has an extra 16 bits tacked onto it, making it 32 bit. Basically, they both serve the same purpose (accumulators).
Edit: as to why it's used to store temporary values, well, working with registers is a LOT faster than with RAM. Technically, you could stock temporary values in RAM, but it would be rather unefficient. For instance...
SomeValue = (SomeValue / 2) + (OtherValue - SomeValue) * 1.5
...would have to be transformed into...
TempA = OtherValue
TempA -= SomeValue
TempA *= 1.5
TempB = SomeValue
TempB /= 2
SomeValue = TempB
SomeValue += TempA
...which adds a good deal of overhead. You have to load and write variables a lot, and since assembly can only work with registers directly in the first place, you'd only end up wasting your time and chewing up unecessary cycles.
[edited by - RuneLancer on March 3, 2003 9:48:27 AM]
+----------------------------------+| EAX |+----------------------------------++-----------------+----------------+| Unnamed | AX |+-----------------+--------+-------++-----------------+--------+-------+| Unnamed | AH | AL |+-----------------+--------+-------+
EAX refers to the full 32bits,
AX refers to the lower 16bits that EAX names,
AH refers to the upper 8bits that AX names,
AL refers to the lower 8bits that AX names.
I am unsure why it is used so much for strogin temporary values, but I think I read somewhere that it was faster (closer to the circuitry that actually performs the additions.)
And unlike RuneLancer said, it is my understanding (not sure, I am still learning ASM myself), that you can directly refer to RAM, but it is slow as hell compared to just using the CPU's built in memory.
[edited by - yummy_potatoes on March 3, 2003 2:03:12 PM]
The reasons (E)AX is used to store temporary variables are as follows:
1. Certain instructions (f.i. mov, add, sub...) cannot accept arguments in the form mem32,mem32... that is the following is invalid:
mov tmp1,tmp2
Instead, you have to do the following:
mov ax,tmp1
mov tmp2,ax
Obviously, to just store tmp1->ax in the first place is more efficient than moving it into ax every time.
2. Certain other instructions (f.i. mul and imul) automatically use the (e)ax register to preform multiplication, that is the mul works as follows:
mov ax,tmp1
mul tmp2
mov result,ax
and not:
mul tmp1,ax ; or any similiar combination of operands
3. Add to that the fact that accessing registers is significantly faster than accessing memory (registers are on the processor whereas memory is usually located over a bus).
-- Exitus Acta Probat --
1. Certain instructions (f.i. mov, add, sub...) cannot accept arguments in the form mem32,mem32... that is the following is invalid:
mov tmp1,tmp2
Instead, you have to do the following:
mov ax,tmp1
mov tmp2,ax
Obviously, to just store tmp1->ax in the first place is more efficient than moving it into ax every time.
2. Certain other instructions (f.i. mul and imul) automatically use the (e)ax register to preform multiplication, that is the mul works as follows:
mov ax,tmp1
mul tmp2
mov result,ax
and not:
mul tmp1,ax ; or any similiar combination of operands
3. Add to that the fact that accessing registers is significantly faster than accessing memory (registers are on the processor whereas memory is usually located over a bus).
-- Exitus Acta Probat --
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement