Tipurile de date diferă în primul rând prin dimensiunea pe care o ocupă.
C | Assembly |
---|---|
#include <stdio.h> int main(void) { char a1 = 1 short a2 = 2; int a3 = 3; long a4 = 4; float a5 = 5; long long a6 = 6; double a7 = 7; return 0; } | LC1: .long 0 .long 1075576832 mov BYTE PTR [ebp-1], 1 mov WORD PTR [ebp-4], 2 mov DWORD PTR [ebp-8], 3 mov DWORD PTR [ebp-12], 4 mov eax, 0x40a00000 mov DWORD PTR [ebp-16], eax mov DWORD PTR [ebp-24], 6 mov DWORD PTR [ebp-20], 0 fld QWORD PTR LC1 fstp QWORD PTR [ebp-32] |
Pentru a putea observa ce se întâmplă la alocarea unui șir, considerăm, pe rând, următoarele exemple.
Definițim un șir de caractere în funcția main.
C | Assembly |
---|---|
#include <stdio.h> int main(void) { char *p = "Ana are mere"; return 0; } | .file "test.c" .intel_syntax .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "Ana are mere\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: push ebp mov ebp, esp sub esp, 8 and esp, -16 mov eax, 0 add eax, 15 add eax, 15 shr eax, 4 sal eax, 4 mov DWORD PTR [ebp-8], eax mov eax, DWORD PTR [ebp-8] call __alloca call ___main mov DWORD PTR [ebp-4], OFFSET FLAT:LC0 mov eax, 0 leave ret |
Variabila p reprezintă un pointer ce va fi inițializat cu adresa șirului global ce poate fi folosit folosind label-ul LC0.
Vom schimba definiția variabilei, astfel încât să forțăm o copiere a datelor pe stivă.
C | Assembly |
---|---|
#include <stdio.h> int main(void) { char p[] = "Ana are mere"; return 0; } | .file "test.c" .intel_syntax .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "Ana are mere\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: push ebp mov ebp, esp sub esp, 40 and esp, -16 mov eax, 0 add eax, 15 add eax, 15 shr eax, 4 sal eax, 4 mov DWORD PTR [ebp-28], eax mov eax, DWORD PTR [ebp-28] call __alloca call ___main mov eax, DWORD PTR LC0 mov DWORD PTR [ebp-24], eax mov eax, DWORD PTR LC0+4 mov DWORD PTR [ebp-20], eax mov eax, DWORD PTR LC0+8 mov DWORD PTR [ebp-16], eax movzx eax, BYTE PTR LC0+12 mov BYTE PTR [ebp-12], al mov eax, 0 leave ret |
Observăm că se vor folosi chunk-uri de DWORD octeți (4 octeți) și se vor folosi regiștrii pentru a copia valorile dintr-o parte în alta.
Pentru a forța compilatorul să genereze cod ce folosește instrucțiuni repetitive, vom folosi un șir mai lung:
C | Assembly |
---|---|
int main(void) { char p[] = "Ana are mere si pere si multe alte fructe."; return 0; } | .file "test.c" .intel_syntax .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" .align 4 LC0: .ascii "Ana are mere si pere si multe alte fructe.\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: push ebp mov ebp, esp push edi push esi sub esp, 64 and esp, -16 mov eax, 0 add eax, 15 add eax, 15 shr eax, 4 sal eax, 4 mov DWORD PTR [ebp-60], eax mov eax, DWORD PTR [ebp-60] call __alloca call ___main lea edi, [ebp-56] mov esi, OFFSET FLAT:LC0 cld mov ecx, 43 rep movsb mov eax, 0 lea esp, [ebp-8] pop esi pop edi pop ebp ret |
În acest caz, copierea a fost făcută folosind alăturarea de instrucțiuni rep movsb. Aceasta copiază octet cu octet de ecx ori.