Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Začátek v Assembleru

Aktivity
Avatar
švrčajs
Člen
Avatar
švrčajs:24.2.2015 18:20

Zdarec, dostal jsem úkol naprogramovat funkce na výpočet objemů, obsahů atd. naprogramované to mám, ale hází mi to divné čísla, nekoukl by mi někdo na to, kde dělám chyby ?

// ConsoleApplication9.cpp : Defines the entry point for the console application.
//
#include "math.h"
#include "stdafx.h"

int obvod_obdelnika(int a, int b)
{
        _asm {
                mov eax, a
                add eax, b
                imul eax, 2
        }
}
int obsah_obdelnika(int a, int b)
{
        _asm {
                mov eax, a
                imul eax, b
        }
}
int obvod_ctverce(int a)
{
        _asm {
                mov eax, a
                imul eax, 4
        }
}
int obsah_ctverce(int a)
{
        _asm {
                mov eax, a
                imul eax, a
        }

}
int obvod_trojuhelnika(int a, int b, int c)
{
        _asm {
                mov eax, a
                add eax, b
                add eax, c
        }
}
int obvod_trojuhelnika2(int a)
{
        _asm {
                mov eax, a
                imul eax, 3
        }
}
int obsah_trojuhelnika2(int a, int b)  //pravouhly(s=(b*c)/2
{
        _asm {
                mov eax, a
                mov ebx, 2
                imul eax, b
                idiv eax
        }

}
int obsah_trojuhelnika3(int a, int va) //vyska a strana! a*va/2
{
        _asm {
                mov eax, a
                mov ebx, 2
                imul eax, va
                idiv eax

        }
}

int objem_krychle(int a)
{
        _asm {
                mov eax, a
                imul eax, a
                imul eax, a
        }
}

int obsah_trojuhelnika_heronovo_pravidlo(int a, int b, int c)
{
        int s = 0;
        int temp = s;
        //sko
        _asm {
                mov eax, a
                mov ebx, 2
                add eax, b
                add eax, c
                idiv eax
                mov s, eax

                mov eax, temp
                sub eax, a
                imul eax, s
                movs s, eax

                mov eax, temp
                sub eax, b
                imul eax, s
                movs s, eax

                mov eax, temp
                sub eax, c
                imul eax, s
                movs s, eax
        }

        s = sqrt(s);
        return s;
}

int _tmain(int argc, _TCHAR* argv[])
{

        printf("Obvod obdelniku: %i \nObsah obdelníku: %i\n Obvod ctverce: %i\n Obsah ctverce: %i\n Obvod toruhelnika1: %i\n Obvod toruhelnika2: %i\n Obsah toruhelnika2: %i\n Obsah toruhelnika3: %i\n Objem krychle: %i\n Heron: %i\n", obvod_obdelnika(2, 4), obsah_obdelnika(2, 4), obvod_ctverce(2), obsah_ctverce(4),obvod_trojuhelnika(2,4,5), obvod_trojuhelnika2(5), obsah_trojuhelnika2(2,5),obsah_trojuhelnika3(5,3), objem_krychle(6),obsah_trojuhelnika_heronovo_pravidlo(5,9,6));
        system("pause");
        return 0;
}
 
Odpovědět
24.2.2015 18:20
Avatar
David Novák
Tvůrce
Avatar
Odpovídá na švrčajs
David Novák:24.2.2015 18:36

Zatím jsem nezkoušel ASM používat v kombinaci s C, ale normálně je "a" adresa proměnné a "[a]" hodnota proměnné
takže zkus ty proměnné uzavřít do [] závorek..

_asm {
      mov eax, [a]
      add eax, [b]
      imul eax, 2
}
Nahoru Odpovědět
24.2.2015 18:36
Chyba je mezi klávesnicí a židlí.
Avatar
Odpovídá na švrčajs
Luboš Běhounek Satik:24.2.2015 19:00

Napr. ve funkci obsah_trojuhelnika3 mas chybku:
delis registrem eax misto registru ebx.
a jeste nezapomen, ze se do toho micha registr edx, takze si ho pro jistotu vynuluj:

_asm {
                mov eax, a
                mov ebx, 2
                imul eax, va
                xor edx, edx
                idiv ebx
        }

A jinak o volacich konvencich uz jsi predpokladam slysel - takze tenhle kod v nekterych kompilatorech nemusi vzdy fungovat.

Nahoru Odpovědět
24.2.2015 19:00
https://www.facebook.com/peasantsandcastles/
Avatar
Martin Dráb
Tvůrce
Avatar
Martin Dráb:24.2.2015 20:30

Ano, na konvence je třeba dávat pozor, zejména na ty používané překladači, pokud není řečeno jinak (a jedná se o normální prostředí). Ty obvykle předávají část parametrů v registrech, zbytek na zásobníku. Nevím, zda by pak určování parametru přes jeho jméno v hranatých závorkách fungovalo. Ale možné to je. Například u konvencí jako cdecl či fastcall se předává první parametr v ECX, druhý v EDX (pro tvůj 32bitový případ), dál si to na x86 nepamatuju.

Také nezapomeň na to (ale to už je spíš optimalizace), že existují instrukce pro bitové posuvy, které lze využít pro snadné (a rychlé) násobení či dělení mocninou dvojky. Bitový posuv vlevo (SHL) odpovídá násobení, aritmetický bitový posuv vpravo (SAR) odpovídá dělení.

Nahoru Odpovědět
24.2.2015 20:30
2 + 2 = 5 for extremely large values of 2
Avatar
švrčajs
Člen
Avatar
švrčajs:28.2.2015 11:48

Chlapi díky, koukl jsem na to a už to počítá správně... Jen mám takový menší problém s tím Heronovým pravidlem, hází mi to error s kernelem ("Unhandled exception at 0x75C985EC (kernel32.dll) in OS1-cv2.exe: 0xC0000005: Access violation executing location 0x75C985EC.") Takže na to se budu ještě muset podívat :D

// ConsoleApplication9.cpp : Defines the entry point for the console application.
//
#include <math.h>
#include "stdafx.h"

int obvod_obdelnika(int a, int b)
{
        _asm {
                mov eax, a
                add eax, b
                imul eax, 2
        }
}
int obsah_obdelnika(int a, int b)
{
        _asm {
                mov eax, a
                imul eax, b
        }
}
int obvod_ctverce(int a)
{
        _asm {
                mov eax, a
                imul eax, 4
        }
}
int obsah_ctverce(int a)
{
        _asm {
                mov eax, a
                imul eax, a
        }

}



int obvod_trojuhelnika(int a, int b, int c)  //není řešen trojúhelníková nerovnost !
{
        _asm {
                mov eax, a
                add eax, b
                add eax, c
        }
}
int obvod_trojuhelnika2(int a)
{
        _asm {
                mov eax, a
                imul eax, 3
        }
}
int obsah_trojuhelnika2(int a, int b)  //pravouhly(s=(b*c)/2
{
        _asm {
                mov eax, a
                mov ebx, 2
                imul eax, b
                xor edx, edx
                idiv ebx
        }

}
int obsah_trojuhelnika3(int a, int va) //vyska a strana! a*va/2
{
        _asm {
                mov eax, a
                mov ebx, 2
                imul eax, va
                xor edx, edx
                idiv ebx
        }
}

int objem_krychle(int a)
{
        _asm {
                mov eax, a
                imul eax, a
                imul eax, a
        }
}

double obsah_trojuhelnika_heronovo_pravidlo(int a, int b, int c)
{
        int s = 0;
        int temp = s;
        double vysledek = 0;
        //sko
        _asm {
                mov eax, a
                        mov ebx, 2
                        add eax, b
                        add eax, c
                        idiv eax
                        mov s, eax

                        mov eax, temp
                        sub eax, a
                        imul eax, s
                        movs s, eax

                        mov eax, temp
                        sub eax, b
                        imul eax, s
                        movs s, eax

                        mov eax, temp
                        sub eax, c
                        imul eax, s
                        movs s, eax
        }

        vysledek = sqrt(s);
        return vysledek;
}

int _tmain(int argc, _TCHAR* argv[])
{
        double i = 0;
        i=obvod_obdelnika(2, 4);
        i=obsah_obdelnika(2, 4);
        i=obvod_ctverce(2);
        i=obsah_ctverce(4);
        i=obvod_trojuhelnika(2, 4, 5);
        i=obvod_trojuhelnika2(5);
        i=obsah_trojuhelnika2(2, 5);
        i=obsah_trojuhelnika3(5, 3);
        i=objem_krychle(6);
        i=obsah_trojuhelnika_heronovo_pravidlo(5, 9, 6);
        system("pause");
        return 0;
}
 
Nahoru Odpovědět
28.2.2015 11:48
Avatar
Odpovídá na švrčajs
Luboš Běhounek Satik:28.2.2015 14:47

jseš si jistej těma movs instrukcema místo mov? :)

Nahoru Odpovědět
28.2.2015 14:47
https://www.facebook.com/peasantsandcastles/
Avatar
švrčajs
Člen
Avatar
švrčajs:1.3.2015 20:10

Jsem kus vola :D přepsal jsem to na mov, ale i tak to nejde :D hází mi to enormní čísla a nevím co s tím :D

 
Nahoru Odpovědět
1.3.2015 20:10
Avatar
Odpovídá na švrčajs
Libor Šimo (libcosenior):2.3.2015 9:10

Ahoj, v čom to kompiluješ? Knižnica stdafx.h už je súčasťou komplilátora, alebo si ju niekde stiahol?

Nahoru Odpovědět
2.3.2015 9:10
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na švrčajs
Luboš Běhounek Satik:2.3.2015 9:59

Přidal jsi tam to vynulování edx před idiv?
A nejspíš by jsi to měl řešit i před imul :) .

Nahoru Odpovědět
2.3.2015 9:59
https://www.facebook.com/peasantsandcastles/
Avatar
švrčajs
Člen
Avatar
švrčajs:2.3.2015 20:29

Tak nakonec jsem to udělal takto :D

float obsah_trojuhelnika_heronovo_pravidlo(int a, int b, int c)
{
        int s = 0;
        int temp = 0;


        _asm {
                mov eax, a
                        add eax, b
                        add eax, c
                        mov ebx, 2
                        xor edx, edx
                        idiv ebx
                        mov s, eax

                        ;; s*(s - a)
                        xor ebx, ebx
                        mov ebx, s
                        sub ebx, a
                        xor edx, edx
                        mul ebx

                        ;; ^*(s - b)
                        xor ebx, ebx
                        mov ebx, s
                        sub ebx, b
                        xor edx, edx
                        mul ebx

                        ;; ^^(s - c)
                        xor ebx, ebx
                        mov ebx, s
                        sub ebx, c
                        xor edx, edx
                        mul ebx

                        mov temp, eax

        }


        return sqrt((float)temp);
}
 
Nahoru Odpovědět
2.3.2015 20:29
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.