Dagens tema. Flyt-tall. Koding. 64-bits kode. Hvordan lagres de? Hvordan regner man med dem? Koding av instruksjoner Kodefiler Linking

Like dokumenter
Dagens tema. Flyt-tall. Koding. 64-bits kode. Hvordan lagres de? Hvordan regner man med dem? Koding av instruksjoner Kodefiler Linking

Dagens tema. Representasjon av mantissen En desimalbrøk: 1 1, INF1070 INF1070 INF1070 INF1070

Dagens tema INF2270. Flyt-tall (B&O H-boken 2.4, 3.14) Hvordan lagres de? Hvordan regner man med dem? Bit-fikling (B&O H-boken 2.1.

Dagens tema. Flyt-tall. Koding. Tegnsett. Hvordan lagres de? Hvilke egenskaper har de? Hvordan regner man med dem?

Dagens tema. Representasjon av mantissen En desimalbrøk: 1 1, INF2270 INF2270 INF2270 INF2270

Dagens tema. Funksjonskall. Flyt-tall. Rekursive kall Lokale variable. Hvordan lagres de? Hvordan regner man med dem?

Dagens tema INF2270. Flyt tall (B&O H boken 2.2.3) Hvordan lagres de? Hvordan regner man med dem? Overflyt (B&O H boken )

Notater: INF2270 Assembler

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Oppbygningen av en datamaskin Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Hvordan en prosessor arbeider, del 1

En oppsummering (og litt som står igjen)

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Den siste dagen. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Veien videre... Eksamen

Pensum Hovedtanker Selvmodifiserende Overflyt Veien videre Eksamen. Oppsummering

Dagens tema. Nyttige programmer Programmet make. Hvis én fil endres, hvilke filer må da kompileres på nytt?

Dagens tema. Nyttige programmer Programmet make. Flyt-tall Representasjon av flyt-tall. Standarden IEEE 754. Systemkall i Unix

IN 147 Program og maskinvare. Vanlige feil ved bruk av pekere Feilsøking Debuggere

Minneområder Det er vanlig å dele opp minnet til en prosess i disse ulike områdene: Fast minne Store og små indianere «align» ing struct er

Dagens tema Programmering av x86 Flytting av data Endring av størrelse

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Løsningsforslag til eksamen i INF2270

Å løse eksamensoppgaver

Dagens tema INF1070. Bit fikling. Makroer. Blanding av C og assemblerkode. Mer om Core War. Dag Langmyhr,Ifi,UiO: Forelesning 22. mai 2006 Ark 1 av 25

En oppsummering. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Eksamen. Programmeringsoppgaver Flervalgsoppgaver

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Del 1 En oversikt over C-programmering

Forelesning Datatyper Kap 5.2 Instruksjonsformat Kap 5.3 Flyttall App B

Forhistorien Menneskene har alltid prøvd å lage maskiner for å løse sine problemer. Dagens tema INF1070 INF1070 INF1070

Forhistorien Menneskene har alltid prøvd å lage maskiner for å løse sine problemer. Dagens tema

Datamaskinenes historie Når, hvor og hvorfor ble de første datamaskiner laget? Hvordan har utviklingen gått? Hva inneholder en datamaskin?

Datamaskinenes historie Når, hvor og hvorfor ble de første datamaskiner laget? Hvordan har utviklingen gått? Hva inneholder en datamaskin?

UNIVERSITETET I OSLO

Kapittel 1 En oversikt over C-språket

Dagens tema: Maskinkode. Litt datamaskinhistorie Hva er maskin- og assemblerkode? x86-prosessoren Programkode og variabler

Dagens tema. Er maskinen big endian? Denne funksjonen tester det: INF1070 INF1070 INF1070 INF1070

Debuggere En «debugger» er et meget nyttig feilsøkingsverktøy. Det kan analysere en program dump, Dagens tema INF1070 INF1070 INF1070 INF1070

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen Oppsummering

Dagens tema INF1070. Makroer. Sanntidsprogrammering. Avbrudd. Bruker- og supermodus. Blanding av C og assemblerkode. Selvmodifiserende kode

Løsningsforslag til eksamen i INF2270

Dagens tema. Makroer Ofte gjentar man kodelinjer når man skriver assemblerkode. Da kan det lønne seg å definere en makro:

Dagens tema. Minnestrukturen Grovt sett ser minnet for hver process slik ut: Flytting av data. Programmering av x86

Intro Rask kode x86-op Optimalisering Inline-kode Konklusjon

Programmeringsspråket C

Dagens tema: Enda mer MIPS maskinkode

Programmering av x86. Minnestrukturen i en prosess Flytting av data. Skifting og rotasjoner Hopp. Stakken Rutinekall. Aritmeriske regneoperasjoner

Tall. Binære regnestykker. Binære tall positive, negative heltall, flytende tall

Del 4 Noen spesielle C-elementer

UNIVERSITETET I OSLO

Oversikt Kodegenerering Variabler Setninger Uttrykk While-setningen

Tall. Posisjons-tallsystemer. Representasjon av heltall. Tall positive, negative heltall, flytende tall. Tekst ASCII, UNICODE XML, CSS

IN 147 Program og maskinvare

Tema for siste forelesning:

Dagens tema. Raskere kode [REB&DRO H kap 5]

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

UNIVERSITETET I OSLO

Reelle tall på datamaskin

Dagens tema. Programmering av x86 INF2270. Minnestrukturen i en prosess. Flytting av data Endring av størrelse. Aritmeriske operasjoner Flagg

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema INF2270. Cs preprosessor. Separat kompilering av C funksjoner. C og minnet. Dag Langmyhr,Ifi,UiO: Forelesning 5. februar 2007 Ark 1 av 15

Dagens tema C, adresser og pekere

Ark 3 av 26. printf("i adresse %08x ligger b med verdien %d.\n", &b, b); printf("i adresse %08x ligger a med verdien %d.

Forelesning Instruksjonstyper Kap 5.5

Programmeringsspråket C Del 2

Programmeringsspråket C

Dagens tema. Mer MIPS maskinkode. Maske-operasjoner Skift-operasjoner Lesing og skriving Pseudo-instruksjoner Mer om funksjonskall Registeroversikt

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

TDT4105/TDT4110 Informasjonsteknologi grunnkurs:

UNIVERSITETET I OSLO

Programmeringsspråket C Del 3

Innhold. 2 Kompilatorer. 3 Datamaskiner og tallsystemer. 4 Oppsummering. 1 Skjerm (monitor) 2 Hovedkort (motherboard) 3 Prosessor (CPU)

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse

TDT4105/TDT4110 Informasjonsteknologi grunnkurs:

Programmeringsspråket C

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 2

Programmeringsspråket C Del 2

Del 2 Tabeller, arrays, strenger

Debugging. Tore Berg Hansen, TISIP

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse. INF 5110, 10/5-2011, Stein Krogdahl

UNIVERSITETET I OSLO

Stack. En enkel, lineær datastruktur

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Programmeringsspråket C Del 3. Hans Petter Taugbøl Kragset

Intro Evaluering Rask kode x86-op Optimalisering Inline-kode

Dagens tema. Raskere kode [REB&DRO H kap 5]

Programmering av x86 [REB&DRO H ]

Javas klasse-filer, byte-kode og utførelse (og litt om C# sin CIL-kode)

Programmeringsspråket C Del 2. Michael Welzl

Kjøresystemer. Hva er et kjøresystem? Den abstrakte maskinen SIMPLESEM (2.6) Klassifisering av språk: Parametre (2.7.7) Statiske språk (

Husk å registrer deg på emnets hjemmeside!

Cs preprosessor. Dagens tema. Betinget kompilering

Rutiner [REB&DRO H 3.7]

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Transkript:

Dagens tema Flyt-tall Hvordan lagres de? Hvordan regner man med dem? Koding Koding av instruksjoner Kodefiler Linking 64-bits kode

Hva er flyt-tall? Flyt-tall [REB&DRO H 2.4] Tall med desimalkomma kan skrives på mange måter: 8 388 708,0 8,388708 10 6 8,39 10 6 De to siste ±M G E er såkalte flyt-tall og består av Mantisse («significand») (M). Grunntall («radix») (G). Eksponent (E). Fortegn. Her lagrer man selve tallet og størrelsen hver for seg. Fordelen er at man alltid har like mange tellende sifre.

Hva er flyt-tall? Representasjon av mantissen En desimalbrøk: 3,14159265 har desimaler. En binærbrøk: 11,0010010 har binærer. Brøken tolkes slik: 2 1 Resultatet er 1 2 1 4 1 8 1 16 1 32 1 64 1 128 1 1, 0 0 1 0 0 1 0 2 1 + 2 0 + 2 3 + 2 6 = 2 + 1 + 1 8 + 1 64 3,1406

Normalisering En normalisert mantisse er en binærbrøk med følgende egenskap: 1 M < G For binær representasjon innebærer dette at 1 M < 2 Det er altså alltid ett binært siffer foran binær-kommaet og det vil alltid være 1 (med mindre hele tallet er 0).

Elementene i et flyt-tall Eksponenten Eksponenten lagres normalt med et fast tillegg slik at vi alltid får et positivt tall. (Da kan vi bruke heltallssammenligning av positive flyt-tall.) Grunntallet Grunntallet er nesten alltid 2. Blir ikke lagret.

32-bits flyt-tall Standarden IEEE 754 for 32-bits flyt-tall 31 30 23 22 0 S Eksponent Mantisse Grunntallet er 2. S er fortegnet; 0 for positivt, 1 for negativt. Eksponenten er på 8 bit og lagres med fast tillegg 127. Mantissen er helst normalisert og på 24 bit, men kun de 23 etter binærkommaet lagres.

Eksempler Hvorledes lagres 1,0? 1,0 10 = 1,0 2 som er normalisert. Eksponent er 0+127=127=1111111 2. Fortegnet er 0. 31 30 23 22 0 0 01111111 00000000000000000000000

Eksempler Hvordan lagres 0? Som spesialkonvensjon er 0 representert av kun 0-bit: 31 30 23 22 0 0 00000000 00000000000000000000000

Eksempler Hvorledes lagres 12,8125? 12,8125 10 = 1100,1101 2 = 1,1001101 2 2 3 Eksponent er 3+127=130=10000010 2. Fortegnet er 1. 31 30 23 22 0 1 10000010 10011010000000000000000

Egenskaper Største tall 31 30 23 22 0 0 11111110 11111111111111111111111 er omtrent 2 254 127 2 3,4 10 38. (Eksponenten 0 er reservert for unormaliserte tall og tallet 0, eksponenten 255 for og NAN «not a number».)

Egenskaper Minste normaliserte positive tall 31 30 23 22 0 0 00000001 00000000000000000000000 er omtrent 2 1 127 1 1,2 10 38.

Egenskaper Nøyaktighet Mantissen er på 24 bit, og 2 24 1,7 10 7. Dette gir 7 desimale sifre.

64-bits flyt-tall Standarden IEEE 754 for 64-bits flyt-tall 63 62 52 51 0 S Eksponent Mantisse Endringer: Eksponenten er økt fra 8 til 11 bit. Lagres med fast tillegg 1023. Mantissen er økt fra 24 til 53 bit. Øverste bit lagres stadig ikke.

Egenskaper Største tall Det største tallet som kan lagres, finner vi utfra formelen 2 (211 2) 1023 2 = 2 1023 2 1,8 10 308 Minste positive normaliserte tall 2 1 1023 1 = 2 1022 1 2,2 10 308 Nøyaktighet Mantissen er på 53 bit, og 2 53 9,0 10 15. Dette gir nesten 16 desimale sifre.

Tap av presisjon Flyt-tall er alltid en tilnærming a n + b n = c n I følge Fermats siste teorem er det ingen heltallsløsninger for n > 2, men hva med #include <stdio.h> #include <math.h> 3987 12 + 4365 12 = 4472 12 int main () { double a = 3987, an = pow(a,12), b = 4365, bn = pow(b,12), c = 4472, res = pow(an+bn,1.0/12); printf("12v(an+bn) = %g\n", res); printf("12v(an+bn) = %.14g\n", res); 12v(an+bn) = 4472 12v(an+bn) = 4472.0000000071 c = 4472 printf(" } c = %g\n", c);

Tap av presisjon Siden flyt-tall oftest bare er en tilnærmet verdi, kan dette lett gi uventede feil, spesielt ved subtraksjon. #include <stdio.h> int main (void) { int i; } for (i = 1; i <= 1000000000; i *= 10) { float v1 = 1.1 + (1.0/i); printf("%f\n", (v1-1.1)*i); } return 0; (1.1 + 1 i 1.1) i 1.000000 1.000000 1.000001 0.999951 1.000404 1.003742 0.977516 1.430511 2.384186 23.841858

Intels FDVI-feil Et annet eksempel I 1994 kom Intel Pentium. Den hadde en ny algoritme med tabelloppslag som skulle forbedre ytelsen til det 3-dobbelte for flyt-tallsdivisjon. Dessverre ble 5 av 1066 verdier i tabellen uteglemt, og dette ga av og til en feil i 6. desimal: Q: How many Pentium designers does it take to screw in a light bulb? A: 1.99999274017

Generelt om x87 Å regne med flyt-tall X86 har en egen flyt-tallsprosessor x87: Den har egne registre ST(0) ST(7) som brukes som en stakk; de inneholder double-verdier. 1 ST(0) (ofte bare kalt ST) er toppen. Den har egne instruksjoner. Den har egne flagg C0 C5. Parametre overføres på stakken (som vanlig). Returverdi fra funksjon legges i ST(0). 1 Egentlig lagrer de 80-bits flyt-tall på et eget format.

Diverse operasjoner Konstanter fldz fld1 # Dytter 0.0 på stakken. # Dytter 1.0 på stakken. Lese fra minnet/stakken flds var # Dytter float var på stakken fldl var # Dytter double var på stakken fld %st(1) # Dytter kopi av ST(x) på stakken Skrive til minnet/stakken fsts var # Skriver ST(0) til var som float fstl var # Skriver ST(0) til var som double fst %st(4) # Kopierer ST(0) til ST(x) fstps var # Som instruksjonene over, fstpl var # men popper stakken etterpå. fstp %st(5) #

Diverse operasjoner Konvertering X87 kan konvertere mellom heltall og flyt-tall: filds ivar # Dytter short var på stakken. fildl ivar # Dytter long var på stakken. fildq ivar # Dytter long long var på stakken. fists ivar # Skriver ST(0) til var som short fistl ivar # Skriver ST(0) til var som long fistps ivar # Popper stakken til var som short fistpl ivar # Popper stakken til var som long fistpq ivar # Popper stakken til var som long long Fortegnsoperasjoner fabs fchs # Gjør ST(0) positivt # Snu fortegnet på ST(0)

Diverse operasjoner Aritmetiske operasjoner fadds var # ST(0) += float var faddl var # ST(0) += double var fadd %st(4) # ST(0) += ST(x) faddp # ST(1) = ST(0)+ST(1); popp fiadds ivar # ST(0) += short ivar fiaddl ivar # ST(0) += long ivar Tilsvarende operasjoner finnes for subtraksjon, multiplikasjon og divisjon: fsubs var # ST(0) -= float var fmuls var # ST(0) *= float var fdivs var # ST(0) /= float var

Diverse operasjoner Sammenligninger ftst # Sammenlign ST(0) med 0.0 fcoms ivar # Sammenlign ST(0) med short var fcoml ivar # Sammenlign ST(0) med long var fcom %st(7) # Sammenlign ST(0) med ST(x) fcom fcomps ivar # Som de over, fcompl ivar # men popper etterpå. fcomp %st(7) # # Sammenlign ST(0) med ST(1) fcomp # fcompp # Som fcom men popper to ganger Resultatet havner i flaggene: C3 = 1 om ST(0) = op C0 = 1 om ST(0) < op

Diverse operasjoner Dessverre finnes ingen hopp som sjekker disse flaggene, men vi kan flytte dem over til x86 og teste der. Da havner C3 i Z-flagget og C0 i C-flagget..globl fnotzero # Navn: fnotzero. # Synopsis: Returnerer x, eller 1.0 om x er null. # C-signatur: float fnotzero (float x). fnotzero: pushl %ebp # Standard movl %esp,%ebp # funksjonsstart. flds 8(%ebp) # Dytt x på x87-stakken. ftst # Test mot 0.0. fstsw %eax # Overfør x87-flaggene til EAX sahf # og derfra til x86-flaggene. jnz fn_xit # Om x er null, fstp %st # popp x og fld1 # dytt 1.0 på x87-stakken. fn_xit: popl %ebp # ret # return SP(0).

Diverse operasjoner Andre Det finnes dusinvis av andre instruksjoner, som fsqrt # ST(0) = sqrt(st(0)) fyl2xp1 # ST(1) = ST(1)*log2(ST(0)+1.0) ; popp

Instruksjoner Koding [REB&DRO H 3.1 2].globl add, res.extern n add: pushl %ebp movl %esp,%ebp movl 8(%ebp),%eax a_x: addl n,%eax jz a_x movl %eax,res popl ret.data res:.long 0 %ebp #include <stdio.h> extern int add (int v); extern int res; int n = 17; int main (void) { printf("add(1) = %d", add(1)); printf(" res = %d\n", res); return 0; }

Instruksjoner Vi lager kode av add.s: $ gcc -m32 -Wa,-a -c add.s >add.list GAS LISTING add.s page 1 1.globl add, res 2.extern n 3 4 0000 55 add: pushl %ebp 5 0001 89E5 movl %esp,%ebp 6 8(%ebp),%eax n,%eax 7 0003 8B4508 8 0006 03050000 a_x: movl addl 8 0000 9 000c 74F8 jz a_x 10 000e A3000000 movl %eax,res 10 00 11 12 0013 5D popl %ebp 13 0014 C3 ret 14 15.data 16 0000 00000000 res:.long 0 DEFINED SYMBOLS add.s:4 add.s:16 add.s:8.text:0000000000000000 add.data:0000000000000000 res.text:0000000000000006 a_x UNDEFINED SYMBOLS n

Instruksjoner Hver x86-instruksjon lagres i 1 15 byte. pushl %ebp = 55 pushl = 50+reg %ebp = 5 addl n,%eax = 03 05 00 00 00 00 addl = 3 %eax / minne = 00-000-101 2 = 5 00000000 = addr(n)

Instruksjoner Ellers kan vi legge merke til: Et navn angir en adresse som kan være enten kode eller data. Navnet a_x er lokalt. Navnene add og res er lokalt definert men globalt kjent. Navnet n antas å være globalt kjent og definert i en annen kodefil. Adressen er foreløbig ukjent. Siden avstanden fra jz til a_x er kjent, er den angitt med relativ adresse (F8 16 = 8).

.o-filer Kompilering/assemblering [REB&DRO H 7] En oversetter lager maskinkode i en.o-fil. En linker lager ferdig eksekverbar kode. Source files Relocatable object files main2.c vector.h Translators (cpp, cc1, as) main2.o libvector.a Linker (ld) p2 addvec.o libc.a Fully linked executable object file Static libraries printf.o and any other modules called by printf.o

.o-filer Kodefilen Kan.o-filen rett og slett være de genererte kode-bytene? Nei, av (minst) to grunner: 1 Eksterne referanser må kobles sammen. 1 add.o må fortelle at den trenger en n fra en annen.o-fil. 2 Den må også fortelle at den tilbyr add og res (om noen skulle være interessert). 2 Adressene (til både kode og data) må endres («relokeres»). Derfor må.o-filen opplyse om 1 Hvilke instruksjoner inneholder adresser som skal endres.

.o-filer ELF På Unix-maskiner lagres programkoden i formatet ELF («Executable and Linkable Format»). $ file add.s add.s: ASCII text $ file add.o add.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

.o-filer objdump forteller oss om hva filen inneholder: $ objdump -d add.o add.o: file format elf32-i386 Disassembly of section.text: 00000000 <add>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 45 08 mov 0x8(%ebp),%eax 00000006 <a_x>: 6: 03 05 00 00 00 00 add 0x0,%eax c: 74 f8 je 6 <a_x> e: a3 00 00 00 00 mov %eax,0x0 13: 5d pop %ebp 14: c3 ret $ objdump -r add.o add.o: file format elf32-i386 RELOCATION RECORDS FOR [.text]: OFFSET TYPE VALUE 00000008 R_386_32 n 0000000f R_386_32 res

Kjørbar kode Kjørbar kode Til sist setter linkeren sammen alle kodefilene (*.o) og bibliotekene (*.a) til kjørbar kode. Eksterne referanser kobles sammen og adresser oppdateres. Source files main2.c vector.h Translators (cpp, cc1, as) libvector.a libc.a Static libraries Relocatable object files main2.o addvec.o printf.o and any other modules called by printf.o Linker (ld) p2 Fully linked executable object file

Kjørbar kode Det komplette bildet av minnet i Linux-prosesser ser slik ut: Kernel memory User stack (created at runtime) Memory invisible to user code %esp (stack pointer) Memory-mapped region for shared libraries Run-time heap (created by malloc) brk 0x08048000 Read/write segment (.data,.bss) Read-only segment (.init,.text,.rodata) Loaded from the executable file 0

Kjørbar kode Dynamiske biblioteker Mye kode er felles i mange prosesser: standardbiblioteker grafiske biblioteker Er det mulig å spare plass ved å la prosessene dele kode?

Kjørbar kode Om man bruker dynamiske biblioteker (.so-filer), vil det bare eksistere én kopi av hver enhet i minnet. main2.c Relocatable object file Translators (cpp, cc1, as) main2.o vector.h Linker (ld) libc.so libvector.so Relocation and symbol table info Partially linked executable object file p2 Loader (execve) libc.so libvector.so Fully linked executable in memory Dynamic linker (ld-linux.so) Code and data

Kjørbar kode For å få dette til å fungere, må koden i dynamiske biblioteker være reentrant slik at flere prosesser kan kjøre koden samtidig (dvs ingen variable i faste adresser) posisjonsuavhengig (= «PIC») slik at den kan plasseres hvor som helst i minnet (dvs kun relative adresser i hopp).

Hva er nytt? 64-bits kode [REB&DRO H 3.13] Omtrent alle pc-er i dag kjører en 64-bits kode x86-64 utviklet av AMD. Adresser er 64 bit. Flere registrene %R8 %R15, og alle registrene i 64-bits utgave. Operasjoner har også 64-bits varianter (som addq). Funksjonskall har en annen protokoll (AMD64 ABI for Linux og Mac, Microsoft x64 for Windows).

Hva er nytt? %EAX %AX %RAX %AH %AL %RBX %BH %BL %RCX %CH %CL %RDX %DH %DL %RBP %RSP %RDI %RSI %EBP %BP %BPL %SPL %DIL %SIL %R8D %R8W %R8 %R8B %R9 %R9B %R10 %R10B %R11 %R11B %R12 %R12B %R13 %R13B %R14 %R14B %R15 %R15B

Hva er nytt? Funksjonskall De seks første parametrene ligger i %RDI, %RSI, %RDX, %RCX, %R8, %R9 Øvrige parametre ligger på stakken. Parameterregistrene samt %R10 og %R11 er frie registre, de øvrige er bundne. Returverdien skal ligge i %RAX.

Hva er nytt? Et eksempel.globl sum64 #include <stdio.h> # Navn: sum64. # Synopsis: Summerer en array. extern long sum64 (long a[], long n); # C-signatur: long sum64 (long a[], long n). # Registre: %RDI a (1. parameter) long data[] = { 123, 10000, 1000000, 100000000, # %RSI n (2. parameter) 10000000000, 1000000000000 }; sum64: movq $0,%rax # Initier summen movq %rsi,%rcx # og telleren. s64_l: # Gå i løkke og addq -8(%rdi,%rcx,8),%rax loop s64_l # summer. ret # Ferdig. int main (void) { int size = sizeof(data)/sizeof(long); printf("svaret er %ld.\n", sum64(data,size)); } $ gcc -o test-sum64 test-sum64.c sum64.s $./test-sum64 Svaret er 1010101010123.