Je passe par un exemple de code d'assemblage pour le mode réel 16 bits.
Je suis tombé sur les lignes:
mov bx, cs
mov ds, bx
mov si, OFFSET value1
pop es
mov di, OFFSET value2
qu'est-ce que ça fait? À quoi sert "OFFSET"?
Comme le disent certaines des autres réponses, le mot clé offset
fait référence au décalage par rapport au segment dans lequel il est défini. Notez cependant que les segments peuvent se chevaucher et que le décalage dans un segment peut être différent dans un autre segment. Par exemple, supposons que vous ayez le segment suivant en mode réel
data SEGMENT USE16 ;# at segment 0200h, linear address 2000h
org 0100h
foo db 0
org 01100h
bar db 0
data ENDS
L'assembleur voit que foo
est à l'offset 0100h
à partir de la base de data SEGMENT
, donc partout où il voit offset foo
il mettra la valeur 0100h
, quelle que soit la valeur de DS
à l'époque.
Par exemple, si nous changeons DS
en autre chose que la base du segment data
, l'assembleur suppose:
mov ax, 200h ; in some assemblers you can use @data for the seg base
mov ds, ax
mov bx, offset foo ; bx = 0100h
mov byte ptr [bx], 10 ; foo = 10
mov ax, 300h
mov ds, ax
mov bx, offset foo ; bx = 0100h
mov byte ptr [bx], 10 ; bar = 10, not foo, because DS doesn't match what we told the assembler
Dans le deuxième exemple, DS
est 0300h
, donc la base du segment pointé par DS
est 03000h
. Cela signifie que ds:[offset foo]
pointe vers l'adresse 03000h + 0100h
qui est identique à 02000h + 01100h
, qui pointe vers bar
.
Cela signifie simplement l'adresse de ce symbole. C'est un peu comme l'opérateur & en C, si vous êtes familier avec cela.
offset
signifie que le registre si
sera égal au décalage de la variable valeur1 (pas à sa valeur réelle). Le décalage est l'adresse du début du segment de mémoire où la variable est stockée. Le décalage est généralement relatif au segment ds
(dans votre cas, les registres ds
et cs
pointent vers le même segment).
De Guide du programmeur MASM 6.1 (Microsoft Macro Assembler)
L'opérateur [~ # ~] [~ # ~] Opérateur
Une constante d'adresse est un type spécial d'opérande immédiat qui se compose d'un décalage ou d'une valeur de segment. L'opérateur OFFSET renvoie l'offset d'un emplacement mémoire, comme illustré ici:
mov bx, OFFSET var ; Load offset address
Pour plus d'informations sur les différences entre le comportement MASM 5.1 et le comportement MASM 6.1 liés au décalage, consultez l'annexe A.
Étant donné que les données de différents modules peuvent appartenir à un seul segment, l'assembleur ne peut pas connaître pour chaque module les vrais décalages au sein d'un segment. Ainsi, le décalage pour var, bien qu'une valeur immédiate, n'est pas déterminé avant le temps de liaison.
Si vous lisez attentivement, la valeur finale est déterminée après avoir "lié" votre code objet pour créer une DLL/EXE. Avant la liaison, tout ce que vous avez est une valeur immédiate qui représente le décalage par rapport à l'adresse de base du segment.
Le décalage est essentiellement la distance du point de segment (également appelé point de référence). par exemple, l'adresse de segment est 0000 et l'adresse de décalage ou logique est 0100, alors l'adresse physique peut être comptée en ajoutant les deux paires. Adresse physique = 0000 + 0100 = 0100 Signifie que notre emplacement requis est sur l'adresse de 0100. De même si l'adresse de segment est 1DDD et le décalage est 0100 alors: L'adresse physique est: 1DDD + 0100 = 1EDD
Signifie que notre destination est 1EDD.
En mode x86 16 bits, l'espace d'adressage n'est pas plat; au lieu de cela, les adresses sont composées d'un décalage et d'un "segment". Le "segment" pointe vers un espace de 64 Ko, le décalage se trouve dans cet espace.