Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[gcc/x86] eerste stapjes asm, invalid operands? *

Pagina: 1
Acties:
  • 108 views sinds 30-01-2008
  • Reageer

  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
het moest er maar eens van komen, ik heb me voorgenomen wat asm te gaan leren :)

ik wilde beginnen met wat simpel vervangwerk van kleine code snippets, maar zelfs daar loop ik al tegen problemen op :D

C++:
1
2
3
4
5
6
7
8
9
//        if( a > b ) c = a - b;
        asm("cmp %1, %2\n\t"
            "jnbe skipAddition\n\t"
            "add %0, %1\n\t"
            "sub %0, %2\n\t"
            "skipAddition:"
            : "=a"(c)
            : "b"(a), "m"(b)
            );

wat ik met mijn huidige kennis gedaan dacht te hebben:
code:
1
2
3
4
5
c++ equivalent van wat ik probeer te doen
vergelijk a met b
als a kleiner of gelijk is aan b, ga naar skipAddition
tel c+a op en sla dit op in c
trek b van c af en sla dit op in c

helaas vindt gcc dat dit een slecht plan is:
Error: suffix or operands invalid for `add'
ik had echter gevonden dat het optellen van twee registers geen probleem zou moeten zijn
add reg, reg
add reg, mem
add mem, reg
add reg, immediate data
add mem, immediate data
add eax/ax/al, immediate data
dus mijn vraag: waarom snapt gcc deze opdracht niet :?
alvast bedankt!

oprecht vertrouwen wordt nooit geschaad


  • Johnny
  • Registratie: December 2001
  • Laatst online: 28-11 13:11

Johnny

ondergewaardeerde internetguru

Om wat voor architectuur gaat het? x86 of iets anders?

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


  • user109731
  • Registratie: Maart 2004
  • Niet online
Welke gcc versie? Bij mij compilet het iig prima met:
jan@desktop:~$ gcc --version
gcc (GCC) 4.1.3 20070831 (prerelease) (Ubuntu 4.1.2-16ubuntu1)
Copyright (C) 2006 Free Software Foundation, Inc.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main() {
    signed int c = 200, a = 400, b = 800;
    
    asm("cmp %1, %2\n\t"
        "jnbe skipAddition\n\t"
        "add %0, %1\n\t"
        "sub %0, %2\n\t"
        "skipAddition:"
        : "=a"(c)
        : "b"(a), "m"(b), "a"(c)
        );
    
    printf("a: %d, b: %d, c: %d\n", a, b, c);
    return 0;
}

[ Voor 13% gewijzigd door user109731 op 11-09-2007 08:26 ]


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
het gaat inderdaad om x86 en ik moet er even bij zeggen dat ik g++ gebruik ipv gcc al weet ik niet zeker of dat überhaupt uitmaakt als het om asm gaat.
mijn compiler:
gcc versie 4.1.2 (Ubuntu 4.1.2-0ubuntu4)


daarnaast zijn de inputs a en b één byte groot(unsigned) en is c twee bytes unsigned.

het valt me nu net op dat het daar misgaat, c is twee bytes groot omdat deze wat waardes moet verzamelen zonder over zijn max te gaan.

oprecht vertrouwen wordt nooit geschaad


  • Dido
  • Registratie: Maart 2002
  • Laatst online: 15:08

Dido

heforshe

Ik mis waarschijnlijk iets, maar waar werk je met registers?

(Vroegah heetten die dingen ax, bx, cx en dx, eax, ebx, ecx en edx of al/ah, bl/bh, cl/ch en dl/dh. En wat ik zo snel online kan vinden vertelt me niet dat dara verandering in is gekomen.)

Het lijkt er dus op dat je niet
add reg, reg
add reg, mem
add mem, reg
add reg, immediate data
add mem, immediate data
add eax/ax/al, immediate data
probeert te doen, maar

add mem, mem

en die zie ik niet.

Wat betekent mijn avatar?


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

%0, %1 en %2 worden vervangen door registers die de compiler zelf bij elkaar zoekt. Die vult hij dan met de waardes van de eerste, tweede en derde variabelen in het stukje:
C++:
1
2
 : "=a"(c)
 : "b"(a), "m"(b) 
Dit omdat het inline assembly is en de compiler dus wel moet weten welke registers er gebruikt moeten/kunnen worden.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • Dido
  • Registratie: Maart 2002
  • Laatst online: 15:08

Dido

heforshe

Ik zie, iig in de TS, niet welke registers er gebruikt worden, en ik vraag me af wat het nut ervan is om het niet expliciet aan te geven, in-line of niet.
Wat is er mis met
MOV a, %eax
MOV b, %ebx
MOV c, %ecx
ADD %ecx, %ebx
?

Of mis ik nu iets essentieels in de code-snippets die google me geeft als ik zoek op G++ ASM ?

Het zou me niet verbazen als a en b van 1 byte (ik zie nergens declaraties, maar goed) niet naar een volledig register gemapped worden door de compiler. En het zou me vervolgens niet verbazen als er wat fout gaat als je bijvoorbeeld BX bij ECX gaat ADDen.

[ Voor 28% gewijzigd door Dido op 11-09-2007 09:30 ]

Wat betekent mijn avatar?


  • user109731
  • Registratie: Maart 2004
  • Niet online
Dido schreef op dinsdag 11 september 2007 @ 09:28:
Ik zie, iig in de TS, niet welke registers er gebruikt worden
C++:
1
2
: "=a"(c)
: "b"(a), "m"(b) 

c = %0 = %eax
a = %1 = %ebx
b = %2 = memory
en ik vraag me af wat het nut ervan is om het niet expliciet aan te geven, in-line of niet.
Extended ASM
Ik denk dat de syntax eenvoudiger is: je hoeft niet zelf variabelen in registers te zetten, dat doet de compiler voor je met bovenstaande code. Bovendien kan de compiler misschien beter optimaliseren als bekend is welke registers gebruikt worden. Je kunt bijvoorbeeld ook zeggen dat er een willekeurig register gebruikt mag worden, dan kan de compiler doen wat het beste uitkomt...
offtopic:
ook wel leuk om eens te kijken wat GCC er zelf van maakt met GCC -S. Dan krijg je een .s-bestand met daarin de asm :)

[ Voor 7% gewijzigd door user109731 op 11-09-2007 09:57 ]


  • Dido
  • Registratie: Maart 2002
  • Laatst online: 15:08

Dido

heforshe

Ah, ok :)

Ik heb altijd wantrouwend gestaan tegenover copilers die wat met m'n ASM willen doen. Je gebruikt immers geen ASM omdat het zo leuk staat :P

offtopic:
Zo dacht QB45 dat de programmeur wel zou vergeten om registerwaarden op de stack te zetten in een interrupt-handler - dus dat zette ie er zelf bij. Lullig als je een recursieve functie schrijft :X


Ik mis dan nog steeds initialisatie van %0, of zorgt de compiler daar ook voor?

Wat betekent mijn avatar?


  • Icelus
  • Registratie: Januari 2004
  • Niet online
Nog wat interessante tips:
GCC Inline Assembly — Rules of Engagement

Developer Accused Of Unreadable Code Refuses To Comment


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//        if( c > a ) d = c - a;
//        if( c > b ) d += c - b;
        asm("movw $0, %%ax\n\t"
            "movb $0, %%bh\n\t"
            "movb $0, %%ch\n\t"
            "movb $0, %%dh\n\t"
            "cmpb %%bl, %%cl\n\t"
            "jnbe skipAddition\n\t"
            "movb %%bl, %%al\n\t"
            "subb %%cl, %%al\n\t"
            "skipAddition:\n\t"
            "cmpb %%bl, %%dl\n\t"
            "jnbe skipSecondAddition\n\t"
            "addw %%bx, %%ax\n\t"
            "subw %%dx, %%ax\n\t"
            "skipSecondAddition:"
            : "=a"(d)
            : "b"(c), "c"(a), "a"(d), "d"(b)
            );

dit heb ik nu werkend, ik ben er alleen nog niet helemaal uit hoe de compiler omgaat met verschillende groottes. Als ik twee afzonderlijke bytes wil optellen en in een word wil opslaan, dan moet ik kennelijk eerst de bytes naar words opslaan en deze vervolgens optellen.
Als ik echter een waarde in register al zet, mag ik er dan vanuit gaan dat ah ook vrijstaat voor mijn gebruik? of kan hier een andere waarde in terecht komen.
maw: wordt voor elk register altijd 32bit gereserveerd?

en hoe zit het met 32b alligned geheugenblokken. Gewoon een kwestie van een blok geheugen alloceren en zelf opzoek gaan naar een pointer die deelbaar is door 4?

oprecht vertrouwen wordt nooit geschaad


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Arjan schreef op dinsdag 11 september 2007 @ 17:36:
Als ik twee afzonderlijke bytes wil optellen en in een word wil opslaan, dan moet ik kennelijk eerst de bytes naar words opslaan en deze vervolgens optellen.
Je kan ook gewoon de 2 bytes optellen, en dan aan de hand van de carry flag de high byte op 0 danwel 1 zetten (tip: als je de low byte dan in een *l register opslaat, dan kun je de *h register op 0 of 1 zetten, zodat het hele *x register je word bevat)
Als ik echter een waarde in register al zet, mag ik er dan vanuit gaan dat ah ook vrijstaat voor mijn gebruik? of kan hier een andere waarde in terecht komen.
maw: wordt voor elk register altijd 32bit gereserveerd?
Doel je hiermee op de registerallocatie door gcc? Je kunt sowieso altijd alle registers gebruiken volgens mij, gcc ziet welke registers jij gebruikt en zorgt dat dat niet conflicteert met de omliggende code. Je hoeft je daar dus geen zorgen om te maken
en hoe zit het met 32b alligned geheugenblokken. Gewoon een kwestie van een blok geheugen alloceren en zelf opzoek gaan naar een pointer die deelbaar is door 4?
32 bit alignment, of 32 byte alignment? Ik weet niet wat de spec van gcc's malloc() is, maar doorgaans is dat al 4-, 8- of zelfs 16-byte aligned geheugen (VC++ doet 8 bytes). Maar het idee is idd alignment-1 bytes extra alloceren, en dan de pointer vooruit duwen naar de eerste alignment mogelijkheid: ((int)pointer + alignment - 1) & ~(alignment - 1), zolang 'alignment' een macht is van 2.

[ Voor 7% gewijzigd door .oisyn op 11-09-2007 18:07 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
.oisyn schreef op dinsdag 11 september 2007 @ 18:05:
[...]

Je kan ook gewoon de 2 bytes optellen, en dan aan de hand van de carry flag de high byte op 0 danwel 1 zetten (tip: als je de low byte dan in een *l register opslaat, dan kun je de *h register op 0 of 1 zetten, zodat het hele *x register je word bevat)

[...]
ok, nieuwe poging, met nieuwe problemen :)
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        asm("cmpb %%bl, 2(%%ebx)\n\t"
            "jnbe skipAddition\n\t"
            "movb %%bl, %%al\n\t"
            "subb 2(%%ebx), %%al\n\t"
            "skipAddition:\n\t"
            "cmpb %%bl, 1(%%ebx)\n\t"
            "jnbe skipSecondAddition\n\t"
            "addb %%bl, 2(%%ebx)\n\t"
            "jno noOverflow\n\t"
            "movb $1, 1(%%eax)\n\t"
            "noOverflow:\n\t"
            "subb 1(%%ebx), %%al\n\t"
            "jno skipSecondAddition\n\t"
            "movw $0, %%ax\n\t"
            "skipSecondAddition:"
            : "=a"(d)
            : "b"(base), "a"(d)
            );

ik heb 4 unsigned bytes, daar ga ik wat mee klooien en ik heb 1 word, die ik gebruik voor tussenresultaten.
de 4 bytes zitten verpakt in de 32bits unsigned int genaamd base en d is mijn word.

op regel 12 zit een probleem, hier negeer ik namelijk de eventuele waarde van 1(%%eax) (de overflow)
Kan ik dit oplossen zonder een extra word aan te hoeven maken?

de C++ code ziet er ongeveer zo uit:
C++:
1
2
3
4
5
6
7
        uint16_t d;
        uint32_t base;
        uint8_t &a = ((uint8_t*)&base)[0];
        uint8_t &b = ((uint8_t*)&base)[1];
        uint8_t &c = ((uint8_t*)&base)[2];
        if( c > a ) d = c -a;
        if( c > b ) d += c - b;

[ Voor 5% gewijzigd door Arjan op 11-09-2007 20:31 ]

oprecht vertrouwen wordt nooit geschaad


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Kijk eens naar adc, oftewel add with carry (die telt dus twee waarden op, en telt daar ook nog eens 1 bij op als de carry gezet is).

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
.oisyn schreef op dinsdag 11 september 2007 @ 20:41:
Kijk eens naar adc, oftewel add with carry (die telt dus twee waarden op, en telt daar ook nog eens 1 bij op als de carry gezet is).
ahja, dat had ik ook nog willen vragen, want ik snapte de uitleg niet precies @ Art of Assembly :)

oprecht vertrouwen wordt nooit geschaad


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

In principe is add with carry (net als sbb, subtract with borrow) bedoeld om op te tellen zoals je op de basisschool hebt geleerd. Je zet de twee getallen onder elkaar, en je telt digit bij digit op waarbij je mogelijk steeds 1 onthoudt.

adc doet precies dat. In feite kun je getallen van een willekeurig aantal bytes optellen door bij de least significant byte te beginnen met een gewone add, en dan alle volgende bytes te doen met adc (sneller is het uiteraard als je het met dwords doet ipv met bytes)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
.oisyn schreef op dinsdag 11 september 2007 @ 21:04:
In principe is add with carry (net als sbb, subtract with borrow) bedoeld om op te tellen zoals je op de basisschool hebt geleerd. Je zet de twee getallen onder elkaar, en je telt digit bij digit op waarbij je mogelijk steeds 1 onthoudt.

adc doet precies dat. In feite kun je getallen van een willekeurig aantal bytes optellen door bij de least significant byte te beginnen met een gewone add, en dan alle volgende bytes te doen met adc (sneller is het uiteraard als je het met dwords doet ipv met bytes)
dat vermoeden had ik al, maar trapt adc die ene bit zelf naar de high byte? of moet ik dat zelf doen door bv
code:
1
2
adc $45, al // hier ontstaat een overflow, de carry bit wordt aangezet
adc $0, ah // de eventuele carry bit wordt erbij opgeteld

oprecht vertrouwen wordt nooit geschaad


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

bah, nare AT&T syntax :P
De eerste moet natuurlijk een gewone add zijn, want daar hoef je de carry nog niet bij op te tellen. De carry wordt vanzelf gezet bij overflow. Maar verder klopt het.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
ok, nog een probleem :D

dit compileert, maar lijkt dodgy at least
C++:
1
2
3
4
5
6
uint32_t base;
asm(
    "cmpb %bl, 2(%%ebx)"
    : 
    : "b"(&base)
    );


dit compileert niet, wegens teveel references naar cmp (hetgeen ik raar vind aangezien ik toch cmpb aangeef...
C++:
1
2
3
4
5
6
uint32_t base;
asm(
    "cmpb (%%ebx), 2(%%ebx)"
    : 
    : "b"(&base)
    );

het vermoeden bekruipt me dat gcc inline asm nog net iets lastiger maakt dan asm toch al is :+

oprecht vertrouwen wordt nooit geschaad


Verwijderd

het vermoeden bekruipt me dat gcc inline asm nog net iets lastiger maakt dan asm toch al is
Zeker. Probeer ook vooral niet meteen je code met optimalisaties te compileren.
Het wil nog wel eens fout gaan met het juist reserveren en invullen van de registers (vooral met FP-registers, laat ie per ongeluk wat op de FP-stack staan bv).
Doe eerst gewoon compileren en kijken of het werkt.
En pas daarna kijken of het nog steeds werkt als je ook optimalisatie aanzet.
Ik heb me ook wel eens gek gezocht naar de bug in mijn code... die er dus niet bleek te zijn.

[ Voor 8% gewijzigd door Verwijderd op 11-09-2007 22:14 ]


  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
Na enig zoekwerk ben ik nog steeds niks zinnigs tegen gekomen, maar omdat ik me niet kan voorstellen dat het niet kan in asm, werp ik nog maar eens een vraag op...
code:
1
2
3
4
5
6
7
uint32_t base = 0xFFFFFFFF;
asm(
    "movb $0, %%bl\n\t"
    "etc..."
    : "=b"(base)
    : "b"(base)
    );

na de eerste regel is base 0xFFFFFF00
als ik de twee laagste bytes wil vergelijken kan ik dat doen met
code:
1
cmpb %%bl, %%bh

leuk en aardig, maar wat als ik nu de twee hoogste bytes wil vergelijken?
een pointer van base maken en het volgende
code:
1
cmpb 2(%%ebx), 3(%%ebx)

mag niet, want dan vindt gcc dat ik twee mem's met elkaar aan het vergelijken ben.
Als ik echter mijn code nog op zinnige manier sneller wil krijgen dan moet ik zonder extra registers de volledige 32bits van het register kunnen aanspreken.

wat is de truuk?

oprecht vertrouwen wordt nooit geschaad


Verwijderd

Je kunt de hoogste bytes in een register niet direct addresseren.
Je zult dus moeten gaan shiften of roteren om de bytes onderin te krijgen...
Voordeel van roteren is dat de bits niet verloren gaan.

  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
Verwijderd schreef op woensdag 12 september 2007 @ 10:44:
Je kunt de hoogste bytes in een register niet direct addresseren.
Je zult dus moeten gaan shiften of roteren om de bytes onderin te krijgen...
Voordeel van roteren is dat de bits niet verloren gaan.
oh goodie, dus als ik 0xFFAAFFBB heb dan kan ik nooit AA en BB vergelijken zonder meer dan één register te gebruiken? (shiften verneukt de data in de FF's dus dat is geen optie)
ik kan natuurlijk 2x roteren, 1x op de double word en een keer op een word, maar echt sneller dan meerdere registers gebruiken lijkt me deze methode niet...

[ Voor 14% gewijzigd door Arjan op 12-09-2007 11:20 ]

oprecht vertrouwen wordt nooit geschaad


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom vergelijk je dan niet gewoon een register met mem? Daarnaast kun je natuurlijk ook eerst al en ah omwisselen, zodat je daarna kunt roteren.

FFAAFFBB
omwisselen FF en BB (xchg al, ah) -> FFAABBFF
rotate right 8 -> FFFFAABB

[ Voor 61% gewijzigd door .oisyn op 12-09-2007 11:36 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Sowieso moet je niet teveel met partial registers werken.
De registers al, ah, ax etc bestaan niet meer in hardware.
De processor maakt intern een tijdelijke kopie in een intern register (via register renaming).
Als je zo'n partial register gaat bewerken, werk je dus via die kopie.
Wil je daarna weer het hele register uitlezen, dan moet de processor de twee (of meer) interne registers weer samenvoegen tot een enkel register, wat een stall van de pipeline tot gevolg heeft. Dit kan tot iets van 8 cycles duren.

Kortom, dit is assembly uit de tijd van Fred Flintstone, en levert baggertrage code op bij moderne microprocessors. Compilers zullen deze situaties uit de weg gaan, en efficientere code opleveren dan wat je met de hand aan bitjes bij elkaar zit te proppen.

Moraal van het verhaal: Op x86 zijn er vele manieren om dezelfde operaties te doen... Wees erop bedacht dat veel van die manieren niet efficient zijn, en ga dus niet af op dingen als 'deze methode levert de minste instructies op', want dat is heel misleidend.
Meestal is de 'domste' oplossing ook de snelste. Vergelijken met geheugen is waarschijnlijk de beste optie, omdat dat geheugen toch al wel in L1-cache zit, in de meeste gevallen, en je dus een latency van 2 a 3 cycles hebt bij het uitlezen... verder geen gedoe van registers roteren en partial register stalls en wat nog meer... Je indexeert gewoon meteen de byte die je wilt hebben.

Vuistregel is om de CPU te behandelen alsof je alleen maar 32-bit (of 64-bit in x64-modus) registers hebt, en gebruik te maken van zero-extension of sign-extension bij het verwerken van bytes, words etc. Zie ook de Intel en AMD optimization manuals.

  • Arjan
  • Registratie: Juni 2001
  • Niet online

Arjan

copyright is wrong

Topicstarter
Verwijderd schreef op woensdag 12 september 2007 @ 12:04:
Sowieso moet je niet teveel met partial registers werken.
De registers al, ah, ax etc bestaan niet meer in hardware.
De processor maakt intern een tijdelijke kopie in een intern register (via register renaming).
Als je zo'n partial register gaat bewerken, werk je dus via die kopie.
Wil je daarna weer het hele register uitlezen, dan moet de processor de twee (of meer) interne registers weer samenvoegen tot een enkel register, wat een stall van de pipeline tot gevolg heeft. Dit kan tot iets van 8 cycles duren.

[...]

Vuistregel is om de CPU te behandelen alsof je alleen maar 32-bit (of 64-bit in x64-modus) registers hebt, en gebruik te maken van zero-extension of sign-extension bij het verwerken van bytes, words etc. Zie ook de Intel en AMD optimization manuals.
hehe, ja dan ben ik inderdaad de verkeerde kant op aan het optimaliseren ;)

oprecht vertrouwen wordt nooit geschaad


Verwijderd

Ja, het schrale is dat ik dit al ruim 10 jaar roep (dit probleem bestaat sinds de Pentium Pro), en nog steeds programmeert men op x86 als Fred Flintstone.
Helemaal sneu wordt het als dergelijke mensen ook nog de misplaatste arrogantie hebben om te beweren dat hun code sneller is dan C/C++-code.

Maargoed, leuk dat er toch nog mensen asm willen leren. Maar leer het aub op de goede manier, namelijk gerelateerd aan de microarchitectuur waarvoor je ontwikkelt, want iedere x86-processor verwerkt de instructies op z'n eigen manier.
Ik denk dat het als programmeur nog belangrijker is om je bewust te zijn van die details op microarchitectuur dan het kunnen programmeren van asm zelf. Maar asm is natuurlijk wel de ideale manier om met dergelijke details te experimenteren. In andere talen heb je die controle niet, en is het lastig om inzicht te krijgen in wat je code nou precies doet, en wat nou de beste oplossing is.
Besef ook dat veel bit-operaties ook mogelijk zijn in C++ en andere talen, dus veel trucjes die je in asm leert, kun je ook vertalen naar andere talen. Misschien wat minder efficient dan asm, maar nog wel beter dan de 'naieve' high-level manier, en het voordeel dat het vaak portable is naar andere OSen en instructiesets.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 12 september 2007 @ 13:30:
Ja, het schrale is dat ik dit al ruim 10 jaar roep (dit probleem bestaat sinds de Pentium Pro), en nog steeds programmeert men op x86 als Fred Flintstone.
:D
Interessant, welk medium gebruik jij om Het Woord te verkondigen, als je denkt dat je daarmee de hele asm community bereikt? Wellicht dat ik het ook kan gebruiken voor m'n pet peeves :P

Seriously though, er zijn natuurlijk enorme misvattingen over assembly. Dingen die 20, 30 jaar geleden wellicht waar waren, maar tegenwoordig al helemaal niet meer van toepassing zijn. De grootste valkuil is denken dat een stukje assembly sowieso beter is dan gecompileerde C of C++ code. Wat dat betreft heb ik al jaren geen hand-written assembly meer geschreven (de laatste keer was toen ik nasm 0.96 heb aangepast om de 3dnow! instructies toe te voegen zodat ik met m'n kersverse K6-2 kon spelen), in performance-critical code maak ik gewoon gebruik van de SSE/VMX intrinsics die de C++ compiler me biedt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Interessant, welk medium gebruik jij om Het Woord te verkondigen, als je denkt dat je daarmee de hele asm community bereikt? Wellicht dat ik het ook kan gebruiken voor m'n pet peeves
Ten eerste, ik zeg net dat het blijkbaar niet werkt, dus ik kan dat medium niet aanraden ;)
Serieuzer... niet zozeer dat ik denk dat ikzelf de hele asm community bereik, maar zoals ik zeg, het staat in de manuals van Intel en AMD, en die zouden toch wel de hele asm community moeten bereiken? Of in ieder geval een meerderheid, zodat ik me niet als een roepende in de woestijn voel.
Verder was ik vroeger wel redelijk nauw betrokken bij de win32asm-community op IRC en fora etc, dus je zou hopen dat je daarmee toch wel mensen bereikt... maar nee.

  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 29-11 15:47
Trouwens, om Intel syntax te kunnen gebruiken in gcc assembly, moet je aan gcc de optie "-masm=intel" meegeven. Dat maakt het heel wat prettiger...

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mwoa, het is maar net wat je gewend bent. Als je intel syntax gewend bent is het idd prettiger, maar er zit geen groot nadeel aan AT&T syntax oid. Het is gewoon net iets anders (operanden omgedraaid, andere geheugenaddressering, instructie-postfixes).

[ Voor 17% gewijzigd door .oisyn op 13-09-2007 14:01 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 29-11 15:47
.oisyn schreef op donderdag 13 september 2007 @ 14:00:
Mwoa, het is maar net wat je gewend bent. Als je intel syntax gewend bent is het idd prettiger, maar er zit geen groot nadeel aan AT&T syntax oid. Het is gewoon net iets anders (operanden omgedraaid, andere geheugenaddressering, instructie-postfixes).
Was inderdaad wat te kort door de bocht. Maar ik ben wel van menig dat de Intel syntax voor een nieuweling (zoals de TS aangeeft te zijn) toegankelijker is, omdat de meeste boeken/tutorials/enzovoort de Intel syntax aanhouden. Eerlijk gezegd heb ik nog nooit een x86 assembly boek gezien met AT&T syntax. Ook de reference manuals van Intel, AMD, Via, etc. werken met de Intel syntax.

Onder Linux is NASM ook een toegankelijke assembler met een redelijk grote aanhang.

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 20:54

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe is Nasm tegenwoordig? Zoals ik eerder al zei, ik was vroeger ook vervent Nasm gebruiker (toen nog met name in combinatie met DJGPP - een dos protected mode implementatie van gcc), maar ik had het idee dat het niet lang na de release van 0.97 (of was het 0.98?) een beetje doodgebloed was.

Wat ik echter een groot nadeel vind aan de assembly syntax van gcc in het algemeen (of dat nou AT&T of Intel is) zijn al die irritante procenten, e.d.. Wat dat betreft vind ik de inline syntax van VC++ toch iets fijner, waarin je asm code niet in strings hoeft te staan en waarbij je gewoon C++ identifiers aan kunt spreken vanuit inline asm code. In dat opzicht kan Nasm ook erg helpen idd.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 29-11 15:47
.oisyn schreef op donderdag 13 september 2007 @ 17:01:
Hoe is Nasm tegenwoordig? Zoals ik eerder al zei, ik was vroeger ook vervent Nasm gebruiker (toen nog met name in combinatie met DJGPP - een dos protected mode implementatie van gcc), maar ik had het idee dat het niet lang na de release van 0.97 (of was het 0.98?) een beetje doodgebloed was.
Het project heeft op een gegeven moment weer wat jong bloed gekregen en is doorgegaan. Trouwens NASM was als applicatie toch ook al aardig uitontwikkeld. Maar als er een nieuwe instructieset bekend wordt gemaakt, staat deze aardig vlot in NASM.
Wat ik echter een groot nadeel vind aan de assembly syntax van gcc in het algemeen (of dat nou AT&T of Intel is) zijn al die irritante procenten, e.d.. Wat dat betreft vind ik de inline syntax van VC++ toch iets fijner, waarin je asm code niet in strings hoeft te staan en waarbij je gewoon C++ identifiers aan kunt spreken vanuit inline asm code. In dat opzicht kan Nasm ook erg helpen idd.
Ik heb zelf ook een hekel aan gcc (inline) assembly, ik gebruik ook liever intrinsics voor zover beschikbaar. Eerlijkgezegd, (zelfs) onder Linux gebruik ik liever de Intel compiler... (Ook om nog meer redenen.)

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic

Pagina: 1