DOMANDA Direttiva ASSUME assembler MASM

Pubblicità

Matteo34

Nuovo Utente
Messaggi
104
Reazioni
3
Punteggio
45
Non capisco davvero a cosa serva la direttiva ASSUME(MASM 6.0), da quel che ho capito server per associare un determinato registro di segmento ha un segmento logico, ma in che senso?
Cioè, il seguente codice che cosa comporta:
Codice:
; Asembly code MASM
; x86-16

stack  SEGMENT  PARA  STACK  ;segmento logico stack
   
     db     2 dup("STACK")

stack ENDS

data   SEGMENT   PARA  PUBLIC    ;segmento logico data
   
     var1    dw     200
     var2    dw     100

data ENDS

code  SEGEMENT PARA PUBLIC   ;segmento logico code
  
     ASSUME  ss : stack, ds : data, cs : code ;che diavolo succede qui?

_start:   

       mov  ax, data
       mov  ds, ax ;che è sta roba?

       mov  ax, var1
       add  ax, var2

       ;ritorno del controllo a MS-DOS
       mov   al, 1
       mov   ah, 04ch
       int   21h

code ENDS
      END  _start
Se ho capito bene definisco dei segmenti logici(per far si che sia tutto più comprensibile e ordinato per l'uomo), e in base al registro di segmento alla quale li associo, il contenuto verrà allocato nei 4 segmenti di memoria attiva;
Mi spiego meglio
Codice:
stack  SEGMENT  PARA  STACK  ;segmento logico stack
   
     db     2 dup("STACK")

stack END

ASSUME ss : stack
Quindi l'assume in questo caso fa capire all'assemblatore dove verrà allocato il contenuto de segmenti logici?
è soprattutto, che è sta roba!!!?!?!?!
Codice:
mov  ax, data
mov  ds, ax ;che è sta roba?
Perchè sto memorizzando in ds il contenuto di data, che cosa contiene data, e perchè lo faccio passando per ax e non direttamente in ds?
Ho davvero bisogno di aiuto sono in totale confusione!!!!!!
 
Magari da pc ti rispondo meglio, ora sono da smartphone, sarò un po' sintetico.

Data è un etichetta che crei sopra, rappresenta il segmento dati. Di fatto quando lo assegni al registro ax stai prendendo il suo indirizzo.
DS punta quindi al primo elemento che hai in data.

Con ASSUME stai dicendo appunto all'assembler di "assumere" come base DATA per il segmento DS, piuttosto che CODE per CS.
Se sbagliassi la assume ti ritroveresti con un puntatore alla locazione errata.

Usando assume puoi usare le variabili in DATA senza specificare il segmento a cui ti riferisci (ci pensa l'assembler).
 
Magari da pc ti rispondo meglio, ora sono da smartphone, sarò un po' sintetico.

Data è un etichetta che crei sopra, rappresenta il segmento dati. Di fatto quando lo assegni al registro ax stai prendendo il suo indirizzo.
DS punta quindi al primo elemento che hai in data.

Con ASSUME stai dicendo appunto all'assembler di "assumere" come base DATA per il segmento DS, piuttosto che CODE per CS.
Se sbagliassi la assume ti ritroveresti con un puntatore alla locazione errata.

Usando assume puoi usare le variabili in DATA senza specificare il segmento a cui ti riferisci (ci pensa l'assembler).
non ho ben capito, aspettero che tu sia da computer, comunque grazie per il tempo che dedicate a rispondere a noi comuni mortali : )
 
Eccomi da PC.

Dunque, inizio con il rispondere al tuo quesito: perchè assegnare data al registro AX e non direttamente a ds. Perchè? Perchè non è presente un opcode per trasferire un valore immediato in un registro di segmento. In pratica, un opcode per fare mov ds, data non esiste.

Per farla breve: usando ASSUME DS : data stai dicendo all'assemblatore che tutti i riferimenti definiti in data sono delle componenti offset da associare a DS. Va da sè che DS deve però essere inizializzato, e lo fai con:

Codice:
mov   ax, data
mov   ds, ax

se ometti queste righe noterai che punterà altrove, non essendo inizializzato correttamente.

Codice:
.386                              
STACK_SIZE = 0400h

STACK   SEGMENT  PARA STACK USE16 'STACK'

    db       STACK_SIZE dup (?)

STACK   ENDS

DATA    SEGMENT  PARA PUBLIC USE16 'DATA'

    hello    db "Hello world",'$'

DATA    ENDS


CODE    SEGMENT  DWORD PUBLIC USE16 'CODE'

   assume   cs: CODE           
  
start:

    mov     ax, DATA
    mov     ds, ax
    assume  ds : DATA

    mov     dx, offset hello
    mov     ah, 09h
    int     21h
   
    mov      ah, 4ch             
    mov      al, 00h             
    int      21h 

CODE    ENDS
END      start

Nota che quel mov con ax e data viene codificato come B8 40 00, che è una mov di un valore immediato in AX.

ASSUME viene anche utilizzata in contesti differenti comunque, come per puntare a una struttura e accedere ai campi della stessa.
Ti faccio un esempio di un mio vecchio codice a 32bit, è solo un estratto:

Codice:
findNTHeader proc

  xor     esi, esi
 
  mov     esi, BaseAddress
  add     esi, dosHeader.e_lfanew
  add     esi, 4h ; 4h = size of Signature
 
  ret
findNTHeader endp

Facendo questo:
Codice:
  call    findNTHeader
  assume  esi:ptr IMAGE_FILE_HEADER

Sei in grado di usare ESI in questo modo:
Codice:
  mov     cx, [esi].NumberOfSections

Tornando al tuo codice: se commenti la ASSUME, noterai che non verrà nemmeno assemblato (o almeno non dovrebbe).

Se la cambi in questo modo:
Codice:
     ASSUME  ss : stack, es : data, cs : code ;  NOTA: -> ES e non DS

e vai a guardare l'assemblato, vedrai che per accedere alla locazione "var1" verrà anteposto un prefisso, e il codice sarà: [
Codice:
26 A1 00 00       ; mov   ES:ax, var1
26 03 06 02 00  ; add    ES:ax, var2

(26h è proprio il segment override prefix per usare ES).

Nota che il codice è rimasto:
Codice:
       mov  ax, data
       mov  ds, ax ;che è sta roba?

       mov  ax, var1
       add  ax, var2

Se modifichi di nuovo la assume con DS invece di ES, l'assemblato sarà:

Codice:
A1 00 00       ; mov  ax, var1
03 06 02 00  ; add  ax, var2

Insomma, ricapitolando: se usi la ASSUME dicendo "DATA è contenuto in ES", l'assembler genera i riferimenti verso quelle locazioni (var1 e var2 nel tuo caso) con il segmento ES. Ovviamente, visto che il registro di segmento di default è DS, deve essere utilizzato il segment override prefix (26h -> ES).

A riprova di quanto detto, se usi come ASSUME per data il registro ES, e volessi usare la mov ax, var1 con DS, saresti costretto a specificare il segmento.
Per chiarezza:

Codice:
     ASSUME  ss : stack, es : data, cs : code ;che diavolo succede qui?

_start:  

       mov  ax, data
       mov  ds, ax ;che è sta roba?

       mov  ax, ds:[var1]    ; NOTA QUESTA RIGA
       add  ax, var2

       ;ritorno del controllo a MS-DOS
       mov   al, 1
       mov   ah, 04ch
       int   21h

Nel codice assemblato questa volta vedrai:

Codice:
A1 00 00            ; mov  ax, ds:[var1]
26 03 06 02 00   ; add  ax, var2

Perchè questo? Semplicemente perchè l'associazione di default è il registro DS, quindi in un certo senso hai "bypassato la assume utilizzando il default", che è il registro di segmento DS. Quindi nel primo caso non è presente il prefisso; nel secondo invece viene ancora usato, e quindi il registro di segmento usato sarà ES (questo perchè l'assembler vede che come registro viene "assunto" ES).

Anche se ho messo assieme un pò di cose spero di aver fatto un pò più di chiarezza, in caso contrario fai pure domande.
 
Eccomi da PC.

Dunque, inizio con il rispondere al tuo quesito: perchè assegnare data al registro AX e non direttamente a ds. Perchè? Perchè non è presente un opcode per trasferire un valore immediato in un registro di segmento. In pratica, un opcode per fare mov ds, data non esiste.

Per farla breve: usando ASSUME DS : data stai dicendo all'assemblatore che tutti i riferimenti definiti in data sono delle componenti offset da associare a DS. Va da sè che DS deve però essere inizializzato, e lo fai con:

Codice:
mov   ax, data
mov   ds, ax

se ometti queste righe noterai che punterà altrove, non essendo inizializzato correttamente.

Codice:
.386                             
STACK_SIZE = 0400h

STACK   SEGMENT  PARA STACK USE16 'STACK'

    db       STACK_SIZE dup (?)

STACK   ENDS

DATA    SEGMENT  PARA PUBLIC USE16 'DATA'

    hello    db "Hello world",'$'

DATA    ENDS


CODE    SEGMENT  DWORD PUBLIC USE16 'CODE'

   assume   cs: CODE          
 
start:

    mov     ax, DATA
    mov     ds, ax
    assume  ds : DATA

    mov     dx, offset hello
    mov     ah, 09h
    int     21h
  
    mov      ah, 4ch            
    mov      al, 00h            
    int      21h

CODE    ENDS
END      start

Nota che quel mov con ax e data viene codificato come B8 40 00, che è una mov di un valore immediato in AX.

ASSUME viene anche utilizzata in contesti differenti comunque, come per puntare a una struttura e accedere ai campi della stessa.
Ti faccio un esempio di un mio vecchio codice a 32bit, è solo un estratto:

Codice:
findNTHeader proc

  xor     esi, esi

  mov     esi, BaseAddress
  add     esi, dosHeader.e_lfanew
  add     esi, 4h ; 4h = size of Signature

  ret
findNTHeader endp

Facendo questo:
Codice:
  call    findNTHeader
  assume  esi:ptr IMAGE_FILE_HEADER

Sei in grado di usare ESI in questo modo:
Codice:
  mov     cx, [esi].NumberOfSections

Tornando al tuo codice: se commenti la ASSUME, noterai che non verrà nemmeno assemblato (o almeno non dovrebbe).

Se la cambi in questo modo:
Codice:
     ASSUME  ss : stack, es : data, cs : code ;  NOTA: -> ES e non DS

e vai a guardare l'assemblato, vedrai che per accedere alla locazione "var1" verrà anteposto un prefisso, e il codice sarà: [
Codice:
26 A1 00 00       ; mov   ES:ax, var1
26 03 06 02 00  ; add    ES:ax, var2

(26h è proprio il segment override prefix per usare ES).

Nota che il codice è rimasto:
Codice:
       mov  ax, data
       mov  ds, ax ;che è sta roba?

       mov  ax, var1
       add  ax, var2

Se modifichi di nuovo la assume con DS invece di ES, l'assemblato sarà:

Codice:
A1 00 00       ; mov  ax, var1
03 06 02 00  ; add  ax, var2

Insomma, ricapitolando: se usi la ASSUME dicendo "DATA è contenuto in ES", l'assembler genera i riferimenti verso quelle locazioni (var1 e var2 nel tuo caso) con il segmento ES. Ovviamente, visto che il registro di segmento di default è DS, deve essere utilizzato il segment override prefix (26h -> ES).

A riprova di quanto detto, se usi come ASSUME per data il registro ES, e volessi usare la mov ax, var1 con DS, saresti costretto a specificare il segmento.
Per chiarezza:

Codice:
     ASSUME  ss : stack, es : data, cs : code ;che diavolo succede qui?

_start: 

       mov  ax, data
       mov  ds, ax ;che è sta roba?

       mov  ax, ds:[var1]    ; NOTA QUESTA RIGA
       add  ax, var2

       ;ritorno del controllo a MS-DOS
       mov   al, 1
       mov   ah, 04ch
       int   21h

Nel codice assemblato questa volta vedrai:

Codice:
A1 00 00            ; mov  ax, ds:[var1]
26 03 06 02 00   ; add  ax, var2

Perchè questo? Semplicemente perchè l'associazione di default è il registro DS, quindi in un certo senso hai "bypassato la assume utilizzando il default", che è il registro di segmento DS. Quindi nel primo caso non è presente il prefisso; nel secondo invece viene ancora usato, e quindi il registro di segmento usato sarà ES (questo perchè l'assembler vede che come registro viene "assunto" ES).

Anche se ho messo assieme un pò di cose spero di aver fatto un pò più di chiarezza, in caso contrario fai pure domande.
OK, capito, grazie
 
Pubblicità
Pubblicità
Indietro
Top