[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 554.   Esempi con gli «spostamenti»

In questo capitolo vengono mostrati esempi di programmi estremamente banali, per dimostrare il funzionamento delle istruzioni con cui si eseguono gli spostamenti di bit (scorrimenti e rotazioni), attraverso l'aiuto di GDB (GNU debugger).(1)

Si dà per scontato che si sappiano compilare i programmi con GNU AS, oppure con NASM. Se si utilizza GNU AS, è bene ricordare di inserire l'opzione --gstabs, mentre con NASM è bene aggiungere l'opzione -g, in modo da poter gestire più facilmente GDB, disponendo dei riferimenti al sorgente:

as --gstabs -o nome.o nome.s[Invio]

nasm -g -f elf -o nome.o nome.s[Invio]

Tabella 551.7. Scorrimenti e rotazioni.

Nome Operandi:
dstorg1org2
Descrizione Indicatori
principali:
carry,
parity,
zero, sign,
overflow
SHL
SHR
reg, 1
mem, 1
reg
mem
Fa scorrere i bit, rispettivamente verso sinistra o verso destra (l'ultima cifra perduta finisce nell'indicatore del riporto). Se appare un solo operando, la rotazione viene eseguita CL volte. Se il valore immediato è maggiore di uno, è il compilatore che ripete l'istruzione per più volte.
c p z s o
# · · · #
SAL
reg, 1
mem, 1
reg
mem
Funziona esattamente come SHL, ma esiste in quanto è la controparte di SAR, riferendosi a uno scorrimento aritmetico.
c p z s o
# · · · #
SAR
reg, 1
mem, 1
reg
mem
Fa scorrere i bit verso destra (l'ultima cifra perduta finisce nell'indicatore del riporto), mantenendo il segno originale. Se appare un solo operando, la rotazione viene eseguita CL volte. Se il valore immediato è maggiore di uno, è il compilatore che ripete l'istruzione per più volte.
c p z s o
# · · · ·
RCL
RCR
reg, 1
mem, 1
reg
mem
Ruota i bit, rispettivamente verso sinistra o verso destra, utilizzando anche l'indicatore di riporto (carry). Se appare un solo operando, la rotazione viene eseguita CL volte. Se il valore immediato è maggiore di uno, è il compilatore che ripete l'istruzione per più volte.
c p z s o
t · · · ·
# · · · #
ROL
ROR
reg, 1
mem, 1
reg
mem
Ruota i bit, rispettivamente verso sinistra o verso destra. Se appare un solo operando, la rotazione viene eseguita CL volte. Se il valore immediato è maggiore di uno, è il compilatore che ripete l'istruzione per più volte.
c p z s o
# · · · #

554.1   Scorrimento logico

Viene proposto un esempio in cui si vede l'uso delle istruzioni SHL e SHR. Si parte da un valore che viene fatto scorrere a sinistra, poi viene ripristinato e quindi viene fatto scorrere a destra.

# Scorrimento logico (logic shift)
#
.section .data
op1:    .byte   0b01001100      # 0x4C
#
.section .text
.globl _start
#
_start:
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    shl  $1,  %al       # Sposta a sinistra le cifre di una posizione.
bp1:                    # AL = 0b10011000 0x98 overflow
    shl  $1,  %al       # Sposta a sinistra le cifre di una posizione.
bp2:                    # AL = 0b00110000 0x30 carry, overflow
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    shr  $1,  %al       # Sposta a destra le cifre di una posizione.
bp3:                    # AL = 0b00100110 0x26
    shr  $2,  %al       # Sposta a destra le cifre di due posizioni.
bp4:                    # AL = 0b00001001 0x09 carry
    mov $0,   %ebx      # Restituisce il valore contenuto in AL
    mov %al,  %bl       # copiandolo nella parte inferiore del
    mov $1,   %eax      # registro EBX ed eseguendo la chiamata
    int $0x80           # di sistema 1 (exit).
; Scorrimento logico (logic shift)
;
section .data
op1:    dd      01001100b       ; 0x4C
;
section .text
global _start
;
_start:
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    shl  al, 1          ; Sposta a sinistra le cifre di una posizione.
bp1:                    ; AL = 10011000b 0x98 overflow
    shl  al,  1         ; Sposta a sinistra le cifre di una posizione.
bp2:                    ; AL = 00110000b 0x30 carry, overflow
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    shr  al, 1          ; Sposta a destra le cifre di una posizione.
bp3:                    ; AL = 00100110b 0x26
    shr  al, 2          ; Sposta a destra le cifre di due posizioni.
bp4:                    ; AL = 00001001b 0x09 carry
    mov ebx, 0          ; Restituisce il valore contenuto in AL
    mov bl, al          ; copiandolo nella parte inferiore del
    mov eax, 1          ; registro EBX ed eseguendo la chiamata
    int 0x80            ; di sistema 1 (exit).

Viene mostrato lo stato del registro EAX e degli indicatori, nei vari punti di sospensione previsti:

bp1
eax            0x98     152
eflags         0xa92    [ AF SF IF OF ]

Bisogna tenere presente che l'ultima istruzione eseguita riguarda solo la porzione AL del registro EAX; pertanto, dal momento che il bit più significativo è a uno, si attiva l'indicatore del segno e anche quello del traboccamento, dato che, se lo scorrimento riguardasse un valore con segno, il valore ottenuto non sarebbe più valido (perché a questo punto si sarebbe trasformato in un numero negativo).

bp2
eax            0x30     48
eflags         0xa17    [ CF PF AF IF OF ]

Sempre tenendo conto che le istruzioni eseguite riguardano solo AL, si può osservare che la perdita della cifra più significativa a uno si traduce nell'attivazione del riporto; inoltre, se si trattasse di un valore con segno, anche questa volta si sarebbe verificata un'inversione (da negativo a positivo) e per questo si attiva ancora l'indicatore di traboccamento.

bp3
eax            0x26     38
eflags         0x212    [ AF IF ]

Questo scorrimento a destra fa perdere solo delle cifre a zero, pertanto il segno non cambia e non c'è alcun riporto (resto).

bp4
eax            0x9      9
eflags         0x217    [ CF PF AF IF ]

Questo ulteriore scorrimento, di due posizioni, comporta la fuoriuscita di una cifra a uno che implica l'attivazione dell'indicatore del riporto (resto).

554.2   Scorrimento aritmetico

Viene proposto un esempio analogo a quello della sezione precedente, in cui si vede l'uso delle istruzioni SAL e SAR. Si parte da un valore negativo che viene fatto scorrere a sinistra, poi viene ripristinato e quindi viene fatto scorrere a destra.

# Scorrimento aritmetico
#
.section .data
op1:    .byte   0b11001100      # 0xCC
#
.section .text
.globl _start
#
_start:
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    sal  $1,  %al       # Sposta a sinistra le cifre di una posizione.
bp1:                    # AL = 0b10011000 0x98 carry
    sal  $1,  %al       # Sposta a sinistra le cifre di una posizione.
bp2:                    # AL = 0b00110000 0x30 carry, overflow
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    sar  $1,  %al       # Sposta a destra le cifre di una posizione.
bp3:                    # AL = 0b11100110 0xE6
    sar  $2,  %al       # Sposta a destra le cifre di due posizioni.
bp4:                    # AL = 0b11111001 0xF9 carry
    mov $0,   %ebx      # Restituisce il valore contenuto in AL
    mov %al,  %bl       # copiandolo nella parte inferiore del
    mov $1,   %eax      # registro EBX ed eseguendo la chiamata
    int $0x80           # di sistema 1 (exit).
; Scorrimento aritmetico
;
section .data
op1:    dd      11001100b       ; 0xCC
;
section .text
global _start
;
_start:
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    sal  al, 1          ; Sposta a sinistra le cifre di una posizione.
bp1:                    ; AL = 10011000b 0x98 carry
    sal  al,  1         ; Sposta a sinistra le cifre di una posizione.
bp2:                    ; AL = 00110000b 0x30 carry, overflow
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    sar  al, 1          ; Sposta a destra le cifre di una posizione.
bp3:                    ; AL = 11100110b 0xE6
    sar  al, 2          ; Sposta a destra le cifre di due posizioni.
bp4:                    ; AL = 11111001b 0xF9 carry
    mov ebx, 0          ; Restituisce il valore contenuto in AL
    mov bl, al          ; copiandolo nella parte inferiore del
    mov eax, 1          ; registro EBX ed eseguendo la chiamata
    int 0x80            ; di sistema 1 (exit).

Viene mostrato lo stato del registro EAX e degli indicatori, nei vari punti di sospensione previsti:

bp1
eax            0x98     152
eflags         0x293    [ CF AF SF IF ]

Bisogna tenere presente che l'ultima istruzione eseguita riguarda solo la porzione AL del registro EAX; pertanto, dal momento che il bit più significativo è a uno, è attivo l'indicatore del segno e anche quello del riporto, avendo perduto una cifra a uno. Il numero non ha cambiato di segno e quindi l'indicatore di traboccamento non è attivo.

bp2
eax            0x30     48
eflags         0xa17    [ CF PF AF IF OF ]

Sempre tenendo conto che le istruzioni eseguite riguardano solo AL, si può osservare che anche questa volta è stata persa una cifra più significativa a uno, essendo attivo l'indicatore del riporto, ma la cosa più importante è che adesso il valore ha cambiato di segno e così si vede attivo anche l'indicatore di traboccamento.

bp3
eax            0xe6     230
eflags         0x292    [ AF SF IF ]

Questo scorrimento a destra fa perdere solo delle cifre a zero, pertanto non c'è alcun riporto (resto).

bp4
eax            0xf9     249
eflags         0x297    [ CF PF AF SF IF ]

Questo ulteriore scorrimento, di due posizioni, comporta la fuoriuscita di una cifra a uno che implica l'attivazione dell'indicatore del riporto (resto).

554.3   Rotazione

Viene proposto un esempio analogo a quello delle sezioni precedenti, in cui si vede l'uso delle istruzioni ROL e ROR. Si parte da un valore che viene fatto ruotare a sinistra, poi viene ripristinato e quindi viene fatto ruotare a destra.

# Rotazione
#
.section .data
op1:    .byte   0b11001100      # 0xCC
#
.section .text
.globl _start
#
_start:
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    rol  $1,  %al       # Ruota a sinistra le cifre di una posizione.
bp1:                    # AL = 0b10011001 0x99 carry
    rol  $1,  %al       # Ruota a sinistra le cifre di una posizione.
bp2:                    # AL = 0b00110011 0x33 carry, overflow
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    ror  $1,  %al       # Ruota a destra le cifre di una posizione.
bp3:                    # AL = 0b01100110 0x66 overflow
    ror  $2,  %al       # Ruota a destra le cifre di due posizioni.
bp4:                    # AL = 0b10011001 0x99 carry, overflow
    mov $0,   %ebx      # Restituisce il valore contenuto in AL
    mov %al,  %bl       # copiandolo nella parte inferiore del
    mov $1,   %eax      # registro EBX ed eseguendo la chiamata
    int $0x80           # di sistema 1 (exit).
; Rotazione
;
section .data
op1:    dd      11001100b       ; 0xCC
;
section .text
global _start
;
_start:
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    rol  al, 1          ; Ruota a sinistra le cifre di una posizione.
bp1:                    ; AL = 10011001b 0x99 carry
    rol  al,  1         ; Ruota a sinistra le cifre di una posizione.
bp2:                    ; AL = 00110011b 0x33 carry, overflow
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    ror  al, 1          ; Ruota a destra le cifre di una posizione.
bp3:                    ; AL = 01100110b 0x66 overflow
    ror  al, 2          ; Ruota a destra le cifre di due posizioni.
bp4:                    ; AL = 10011001b 0x99 carry, overflow
    mov ebx, 0          ; Restituisce il valore contenuto in AL
    mov bl, al          ; copiandolo nella parte inferiore del
    mov eax, 1          ; registro EBX ed eseguendo la chiamata
    int 0x80            ; di sistema 1 (exit).

Viene mostrato lo stato del registro EAX e degli indicatori, nei vari punti di sospensione previsti:

bp1
eax            0x99     153
eflags         0x293    [ CF AF SF IF ]

Si deve tenere conto che l'ultima istruzione eseguita riguarda solo la porzione AL del registro EAX. La rotazione ha fatto uscire a sinistra una cifra a uno che rientra nella parte destra. La cifra spostata la si ritrova nell'indicatore di riporto.

bp2
eax            0x33     51
eflags         0xa93    [ CF AF SF IF OF ]

Questa ulteriore rotazione a sinistra fa uscire un'altra cifra a uno, che viene segnalata nel riporto, ma il bit più significativo passa a zero e quindi l'indicatore di traboccamento viene attivato.

bp3
eax            0x66     102
eflags         0xa92    [ AF SF IF OF ]

Questa rotazione a destra fa perdere solo una cifra a zero, pertanto non c'è alcun riporto (resto), ma dal momento che rientra a sinistra, l'indicatore di traboccamento manifesta l'ipotesi di cambiamento del segno.

bp4
eax            0x99     153
eflags         0xa93    [ CF AF SF IF OF ]

Questa ulteriore rotazione, di due posizioni, comporta la fuoriuscita di una cifra a uno che implica l'attivazione dell'indicatore del riporto (resto). Dal momento che la cifra rientra a sinistra, l'indicatore di traboccamento segnala l'ipotesi di cambiamento del segno.

554.4   Rotazione con riporto

Viene proposto un esempio analogo a quello della sezione precedente, in cui si vede l'uso delle istruzioni RCL e RCR. Si parte da un valore che viene fatto ruotare a sinistra, poi viene ripristinato e quindi viene fatto ruotare a destra. Qui viene usata anche l'istruzione CLC per azzerare il riporto.

# Rotazione con riporto
#
.section .data
op1:    .byte   0b11001101      # 0xCD
#
.section .text
.globl _start
#
_start:
    clc                 # Azzera il riporto.
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    rcl  $1,  %al       # Ruota a sinistra le cifre di una posizione.
bp1:                    # AL = 0b10011010 0x9A carry
    rcl  $1,  %al       # Ruota a sinistra le cifre di una posizione.
bp2:                    # AL = 0b00110101 0x35 carry, overflow
    clc                 # Azzera il riporto.
    mov  op1, %al       # Inizializza AL con il valore di partenza.
    rcr  $1,  %al       # Ruota a destra le cifre di una posizione.
bp3:                    # AL = 0b01100110 0x66 carry, overflow
    rcr  $2,  %al       # Ruota a destra le cifre di due posizioni.
bp4:                    # AL = 0b01011001 0x59 carry, overflow
    mov $0,   %ebx      # Restituisce il valore contenuto in AL
    mov %al,  %bl       # copiandolo nella parte inferiore del
    mov $1,   %eax      # registro EBX ed eseguendo la chiamata
    int $0x80           # di sistema 1 (exit).
; Rotazione con riporto
;
section .data
op1:    dd      11001101b       ; 0xCD
;
section .text
global _start
;
_start:
    clc                 ; Azzera il riporto.
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    rcl  al, 1          ; Ruota a sinistra le cifre di una posizione.
bp1:                    ; AL = 10011010b 0x9A carry
    rcl  al,  1         ; Ruota a sinistra le cifre di una posizione.
bp2:                    ; AL = 00110101b 0x35 carry, overflow
    clc                 ; Azzera il riporto.
    mov  al, [op1]      ; Inizializza AL con il valore di partenza.
    rcr  al, 1          ; Ruota a destra le cifre di una posizione.
bp3:                    ; AL = 01100110b 0x66 carry, overflow
    rcr  al, 2          ; Ruota a destra le cifre di due posizioni.
bp4:                    ; AL = 01011001b 0x59 carry, overflow
    mov ebx, 0          ; Restituisce il valore contenuto in AL
    mov bl, al          ; copiandolo nella parte inferiore del
    mov eax, 1          ; registro EBX ed eseguendo la chiamata
    int 0x80            ; di sistema 1 (exit).

Viene mostrato lo stato del registro EAX e degli indicatori, nei vari punti di sospensione previsti:

bp1
eax            0x9a     154
eflags         0x293    [ CF AF SF IF ]

Si deve tenere conto che l'ultima istruzione eseguita riguarda solo la porzione AL del registro EAX. La rotazione ha fatto uscire a sinistra una cifra a uno che passa nel riporto, mentre a destra entra il valore precedente del riporto (zero).

bp2
eax            0x35     53
eflags         0xa93    [ CF AF SF IF OF ]

Questa ulteriore rotazione a sinistra fa uscire un'altra cifra a uno che passa nel, mentre entra a destra la cifra a uno del riporto precedente. Dopo la rotazione il bit più significativo passa a zero e quindi l'indicatore di traboccamento viene attivato.

bp3
eax            0x66     102
eflags         0xa93    [ CF AF SF IF OF ]

Questa rotazione a destra fa perdere una cifra a uno che si trasferisce del riporto; inoltre, dato che il riporto precedente era zero, a sinistra si inserisce una cifra a zero, la quale fa scattare l'indicatore di traboccamento (nell'ipotesi di un valore con segno).

bp4
eax            0x59     89
eflags         0xa93    [ CF AF SF IF OF ]

Questa ulteriore rotazione, di due posizioni, comporta la fuoriuscita di una cifra a zero e poi a uno che implica l'attivazione dell'indicatore del riporto (resto). In precedenza c'era stato un riporto che attualmente risulta inserito subito dopo la cifra più significativa. Dal momento l'ultimo scorrimento (dei due eseguiti qui) fa cambiare la cifra più significativa, si attiva l'indicatore di traboccamento.


1) GDB   GNU GPL


Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome esempi_con_gli_171_spostamenti_187.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory