Les registres de segment sont tous en taille 16 bits. Comparez cela aux registres e?x
, qui ont une taille de 32 bits. Évidemment, ces deux choses n'ont pas la même taille, ce qui incite votre assembleur à générer une erreur de "non-concordance de taille d'opérande" - les tailles des deux opérandes ne correspondent pas.
On peut supposer que vous voulez initialiser le registre de segment avec les 16 bits inférieurs du registre, de sorte que vous feriez quelque chose comme:
mov ds, ax
mov es, bx
En outre, non, vous n'avez pas réellement besoin d'initialiser le segment enregistre à chaque itération de la boucle. Ce que vous faites maintenant est d'incrémenter le segment et de forcer le décalage à 0, puis de copier 4 DWORD. Ce que vous devriez faire est de laisser le segment seul et d'incrémenter le offset (que l'instruction MOVSD
fait implicitement).
mov eax, _kernel_segment ; TODO: see why these segment values are not
mov ebx, _kernel_reloc_segment ; already stored as 16 bit values
mov ecx, _kernel_para_size
mov ds, ax
mov es, bx
xor esi, esi
xor edi, edi
.loop:
movsd
movsd
movsd
movsd
dec ecx
jnz .loop
Mais notez que l'ajout du REP
prefix à l'instruction MOVSD
vous permettra de le faire encore plus efficacement. Cela fait MOVSD
un total de ECX
fois. Par exemple:
mov ds, ax
mov es, bx
xor esi, esi
xor edi, edi
shl ecx, 2 ; adjust size since we're doing 1 MOVSD for each ECX, rather than 4
rep movsd
Un peu contre-intuitive, si votre processeur implémente the ERMSB optimization (Intel Ivy Bridge et versions ultérieures), REP MOVSB
peut effectivement être plus rapide que REP MOVSD
, pour que vous puissiez faire:
mov ds, ax
mov es, bx
xor esi, esi
xor edi, edi
shl ecx, 4
rep movsb
Enfin, Bien que vous ayez commenté l'instruction CLD
dans votre code, vous devez l'avoir afin de vous assurer que les mouvements se déroulent conformément au plan. Vous ne pouvez pas compter sur le drapeau de direction ayant une valeur particulière; vous devez l'initialiser vous-même à la valeur que vous voulez.
(Une autre alternative serait de diffuser des instructions SIMD ou même des mémoires à virgule flottante, dont aucune ne se soucierait de l'indicateur de direction, ce qui présente l'avantage d'augmenter la bande passante de copie mémoire car bit, ou des copies plus grandes à la fois, mais présente d'autres inconvénients.En cas de noyau, je m'en tiens à MOVSD
/MOVSB
sauf si vous pouvez prouver n'est pas un goulot d'étranglement significatif et/ou vous voulez avoir des chemins optimisés pour différents processeurs.)
merci l'homme, grand mode réel aidé mais quand je reviens de la fonction il ne revient pas – sakura
@sakura: J'ai presque intérêt zéro dans le mode 16 bits obsolète. Je continue à lire à ce sujet dans les questions SO, ce qui est la seule raison pour laquelle j'ai pu écrire cette réponse (heureux que cela a aidé, BTW). Tout ce que je peux recommander est d'avoir un bon débogueur, par exemple. celui intégré à BOCHS, de sorte que vous pouvez faire un seul pas sur votre noyau. –
Après plus de détails sur cette question sont devenus clairs, je ne peux pas m'empêcher de me demander pourquoi vous ne passez pas simplement en mode protégé 32 bits avant de faire cette copie. Vraisemblablement, c'est ce que le noyau va finalement faire de toute façon. Pourquoi voudriez-vous revenir en mode réel? Même en "mode irréel", autant que je sache, vous ne pouvez pas dépasser 1 Mo, donc ce n'est pas vraiment une solution miracle. @sakura –