PROBLEMA completare la parte in assembler

alberto1998

Nuovo Utente
4
0
ciao a tutti, stavo cercando una mano per completare la parte di blocco assembler definita da __asm

Descrizione: Data una stringa C (terminata dal carattere nullo), contenente una frase (ossia parole separate da spazi e/o segni di punteggiatura), trovare la parola più lunga e la parola più corta. In caso di parole di uguale lunghezza, considerare la prima da sinistra. Le due parole vanno copiate in due array di caratteri come stringhe C (terminate dal carattere nullo). I segni di punteggiatura da considerare sono: ".,;:'?!"
Esempi di casi importanti da verificare: “due parole” → “due”, “parole” “parola” → “parola”, “parola” “a, b, c, test, d,” → “a” , “test” “elaborato 3: 2004” → “3” , “elaborato”

C:
#include <stdio.h>

void main()
{
// Variabili
#define MAX_LEN 100
char frase[MAX_LEN] = "Cantami, o Diva, del Pelide Achille l'ira funesta che \
infiniti addusse lutti agli Achei";
char parolaMax[MAX_LEN + 1];
char parolaMin[MAX_LEN + 1];

// Blocco assembler
__asm
{


}

// Stampa su video
printf("%s\n%s\n%s\n", frase, parolaMax, parolaMin);

}
 
Ultima modifica da un moderatore:

Skills07

Head of Development
Staff Forum
Utente Èlite
35,439
11,502
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
Per cortesia metti il codice sotto tag code
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
ciao a tutti, stavo cercando una mano per completare la parte di blocco assembler definita da __asm

Descrizione: Data una stringa C (terminata dal carattere nullo), contenente una frase (ossia parole separate da spazi e/o segni di punteggiatura), trovare la parola più lunga e la parola più corta. In caso di parole di uguale lunghezza, considerare la prima da sinistra. Le due parole vanno copiate in due array di caratteri come stringhe C (terminate dal carattere nullo). I segni di punteggiatura da considerare sono: ".,;:'?!"
Esempi di casi importanti da verificare: “due parole” → “due”, “parole” “parola” → “parola”, “parola” “a, b, c, test, d,” → “a” , “test” “elaborato 3: 2004” → “3” , “elaborato”

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>

void main()
{
// Variabili
#define MAX_LEN 100
char frase[MAX_LEN] = "Cantami, o Diva, del Pelide Achille l'ira funesta che \
infiniti addusse lutti agli Achei";
char parolaMax[MAX_LEN + 1];
char parolaMin[MAX_LEN + 1];

// Blocco assembler
__asm
{


}

// Stampa su video
printf("%s\n%s\n%s\n", frase, parolaMax, parolaMin);

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Ciao, nella sezione c'è questo topic: Regolamento ed informazioni utili sulla sezione Programmazione che riporta le info sull'utilizzo del tag CODE. Vedo che hai inserito "cose"... ripulisco tutto e utilizzo io il tag CODE, ma per favore, la prossima volta utilizzalo (anche perchè ci sono casi come un ciclo che utilizza una variabile come i, [i], che minerebbero la lettura del codice mostrando tutto in corsivo). 😉

Ad ogni modo, quale sarebbe la tua domanda specifica riguardo al blocco asm? Così pare ci stai chiedendo di scriverti tutto l'assembly.
 

alberto1998

Nuovo Utente
4
0
Ciao, nella sezione c'è questo topic: Regolamento ed informazioni utili sulla sezione Programmazione che riporta le info sull'utilizzo del tag CODE. Vedo che hai inserito "cose"... ripulisco tutto e utilizzo io il tag CODE, ma per favore, la prossima volta utilizzalo (anche perchè ci sono casi come un ciclo che utilizza una variabile come i, [i], che minerebbero la lettura del codice mostrando tutto in corsivo). 😉

Ad ogni modo, quale sarebbe la tua domanda specifica riguardo al blocco asm? Così pare ci stai chiedendo di scriverti tutto l'assembly.
si, mi scuso sono nuovo, ho visto ora come si fa, grazie. Comunque il problema sta nel fatto che non so come prendere una parola della frase e confrontarla con un altra della frase.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
si, mi scuso sono nuovo, ho visto ora come si fa, grazie. Comunque il problema sta nel fatto che non so come prendere una parola della frase e confrontarla con un altra della frase.

Non è semplicissimo da scrivere, più che altro perchè c'è anche la condizione relativa ai segni di punteggiatura.

La cosa più semplice probabilmente è:
  1. iniziare a scorrere la stringa e cercare il primo carattere che delimita la parola (segni di punteggiatura riportati sopra nella consegna e lo spazio)
  2. usare 2 registri per mantenere il primo carattere che consideri e l'ultimo che avrai letto
  3. calcolare quindi la lunghezza: è una sottrazione tra i due indici che hai appena calcolato e salvarla in un registro o nello stack
  4. copiare i caratteri tra i 2 indici nei 2 array (aggiungendo il carattere terminatore della stringa)
  5. ripetere il punto 1, se la lunghezza è minore o maggiore di quella calcolata in precedenza, comportarsi di conseguenza (sostituisci la stringa o in un array, o nell'altro)
In teoria facendo così nel punto 4 dovresti eliminare tutti i caratteri presenti dal terminatore in avanti, all'interno di quell'array (per non lasciarlo sporco).
Mi sembra fili abbastanza il tutto, bisognerebbe provare ad implementarlo però, magari esce qualche problema.

Se non ci fossero di mezzo i segni di punteggiatura, sarebbe più semplice scorrere la stringa sino a trovare il carattere "spazio", basterebbe una REPNE SCASB. Non escludo che qualche trick ci sia, sono un pò arrugginito però.

Per copiare la parola negli array di caratteri puoi usare REP MOVSB.
 
  • Mi piace
Reazioni: alberto1998

bigendian

Utente Attivo
749
432
OS
Linux
ma lui non sapra' come si passano le variabili all'assembly. Senza questo, ben poco fara'.

Non si usa __asm {} ma l'extended l'inline assembly

asm asm-qualifiers ( AssemblerTemplate
: OutputOperands
[ : InputOperands
[ : Clobbers ] ])

ad esempio puoi usare 2 blocchi

asm volatile ("....."
: "=D" (parolaMin)
: "S" (frase));

asm volatile ("....."
: "=D" (parolaMax)
: "S" (frase));

rax, rbx, rcx, rdx, rsi, rdi si indicano con lettere, rispettivamentye : a,b,c,d,S,D

Non mi pare un esercizio banale per chi non conosce bene assembly 8086 e sintassi at&t, per altro ancora diversa da inline assembly, in quanto extended.
Per copiare le parole, puoi anche usare un piu chiaro dec + cmp + jne, o "loop", o appunto repnse scasb e compagnia. Hai 16 registiri a disposizione, buon divertimento

[EDITATO] ops, quanto sopra vale per gcc
 
Ultima modifica:
  • Mi piace
Reazioni: alberto1998

Skills07

Head of Development
Staff Forum
Utente Èlite
35,439
11,502
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
Usate il tag CODE i codici sorgente
 
  • Mi piace
Reazioni: Moffetta88

alberto1998

Nuovo Utente
4
0
Non è semplicissimo da scrivere, più che altro perchè c'è anche la condizione relativa ai segni di punteggiatura.

La cosa più semplice probabilmente è:
  1. iniziare a scorrere la stringa e cercare il primo carattere che delimita la parola (segni di punteggiatura riportati sopra nella consegna e lo spazio)
  2. usare 2 registri per mantenere il primo carattere che consideri e l'ultimo che avrai letto
  3. calcolare quindi la lunghezza: è una sottrazione tra i due indici che hai appena calcolato e salvarla in un registro o nello stack
  4. copiare i caratteri tra i 2 indici nei 2 array (aggiungendo il carattere terminatore della stringa)
  5. ripetere il punto 1, se la lunghezza è minore o maggiore di quella calcolata in precedenza, comportarsi di conseguenza (sostituisci la stringa o in un array, o nell'altro)
In teoria facendo così nel punto 4 dovresti eliminare tutti i caratteri presenti dal terminatore in avanti, all'interno di quell'array (per non lasciarlo sporco).
Mi sembra fili abbastanza il tutto, bisognerebbe provare ad implementarlo però, magari esce qualche problema.

Se non ci fossero di mezzo i segni di punteggiatura, sarebbe più semplice scorrere la stringa sino a trovare il carattere "spazio", basterebbe una REPNE SCASB. Non escludo che qualche trick ci sia, sono un pò arrugginito però.

Per copiare la parola negli array di caratteri puoi usare REP MOVSB.
ho provato fare in questo modo ma mi da errore: Eccezione generata in corrispondenza di 0x006253F7 in assembly3.exe: 0xC0000005: violazione di accesso durante la scrittura del percorso 0x00770000
C:
       XOR EBX, EBX
        XOR EAX, EAX
        XOR EDX, EDX
        XOR ESI, ESI
        XOR EDI, EDI
        XOR ECX, ECX

        ; Inizializza lunghezza massima e minima
        MOV dword ptr[lunghezzaMax], 0
        MOV dword ptr[lunghezzaMin], MAX_LEN

        Ciclo :
        MOV AL, frase[EBX]
            CMP AL, 0
            JE Fine

            ; Verifica se il carattere è uno dei segni di punteggiatura
            CMP AL, ','
            JE NoCarattere
            CMP AL, '.'
            JE NoCarattere
            CMP AL, ';'
            JE NoCarattere
            CMP AL, ':'
            JE NoCarattere
            CMP AL, '\''
            JE NoCarattere
            CMP AL, '?'
            JE NoCarattere
            CMP AL, '!'
            JE NoCarattere

            ; Confronta il carattere con lo spazio
            CMP AL, ' '
            JE FineParola

            ; Aggiorna la parola massima
            CMP ECX, dword ptr[lunghezzaMax]
            JG AggiornaParolaMax

            ; Aggiorna la parola minima
            CMP ECX, dword ptr[lunghezzaMin]
            JL AggiornaParolaMin

            JMP Continua

            NoCarattere :
        ; Confronta il carattere con lo spazio
            CMP AL, ' '
            JE FineParola

            JMP Continua

            AggiornaParolaMax :
        MOV dword ptr[lunghezzaMax], ECX
            MOV EDI, ECX
            LEA ESI, parolaMax
            LEA EDX, parolaMax

            MOV ECX, EDI
            JMP Continua

            AggiornaParolaMin :
        MOV dword ptr[lunghezzaMin], ECX
            MOV EDI, ECX
            LEA ESI, parolaMin
            LEA EDX, parolaMin

            MOV ECX, EDI

            Continua :
        MOV[EDX], AL
            INC EDX

            JMP Ciclo

            FineParola :
        MOV[EDX], 0
            JMP Ciclo

            Fine :
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
ho provato fare in questo modo ma mi da errore: Eccezione generata in corrispondenza di 0x006253F7 in assembly3.exe: 0xC0000005: violazione di accesso durante la scrittura del percorso 0x00770000
C:
       XOR EBX, EBX
        XOR EAX, EAX
        XOR EDX, EDX
        XOR ESI, ESI
        XOR EDI, EDI
        XOR ECX, ECX

        ; Inizializza lunghezza massima e minima
        MOV dword ptr[lunghezzaMax], 0
        MOV dword ptr[lunghezzaMin], MAX_LEN

        Ciclo :
        MOV AL, frase[EBX]
            CMP AL, 0
            JE Fine

            ; Verifica se il carattere è uno dei segni di punteggiatura
            CMP AL, ','
            JE NoCarattere
            CMP AL, '.'
            JE NoCarattere
            CMP AL, ';'
            JE NoCarattere
            CMP AL, ':'
            JE NoCarattere
            CMP AL, '\''
            JE NoCarattere
            CMP AL, '?'
            JE NoCarattere
            CMP AL, '!'
            JE NoCarattere

            ; Confronta il carattere con lo spazio
            CMP AL, ' '
            JE FineParola

            ; Aggiorna la parola massima
            CMP ECX, dword ptr[lunghezzaMax]
            JG AggiornaParolaMax

            ; Aggiorna la parola minima
            CMP ECX, dword ptr[lunghezzaMin]
            JL AggiornaParolaMin

            JMP Continua

            NoCarattere :
        ; Confronta il carattere con lo spazio
            CMP AL, ' '
            JE FineParola

            JMP Continua

            AggiornaParolaMax :
        MOV dword ptr[lunghezzaMax], ECX
            MOV EDI, ECX
            LEA ESI, parolaMax
            LEA EDX, parolaMax

            MOV ECX, EDI
            JMP Continua

            AggiornaParolaMin :
        MOV dword ptr[lunghezzaMin], ECX
            MOV EDI, ECX
            LEA ESI, parolaMin
            LEA EDX, parolaMin

            MOV ECX, EDI

            Continua :
        MOV[EDX], AL
            INC EDX

            JMP Ciclo

            FineParola :
        MOV[EDX], 0
            JMP Ciclo

            Fine :

Scusa il delay nella risposta, non avevo a disposizione Windows.

Puoi riportare il codice completo? Due variabili non sono definite, le ho aggiunte io per poter provare il tuo codice.

Ad ogni modo secondo me è "logicamente" errato visto così: prima degli IF di aggiornaparolaminima dovresti leggere tutta la parola arrivando allo spazio. Non dovrebbe minare il funzionamento, o almeno, c'è sicuramente un altro errore importante.

L'errore è che il contatore che utilizzi per scorrere la frase (EBX) non viene mai incrementato. Quello che mi sembra si verifichi è un loop infinito, elabori sempre la 'C'.
Per superare il problema, una cosa di questo tipo:
Codice:
Continua :
    MOV[EDX], AL
    INC EDX
    INC EBX

    JMP Ciclo

FineParola :
    MOV[EDX], 0
    INC EBX
    JMP Ciclo

Il secondo problema che vedo è che non mi sembra modifichi mai i due array di caratteri di parola max e parola min. Verifica anche quello.

Ti conviene affiancare allo sviluppo anche il debugger comunque 😁 su ste cose ci diventi matto altrimenti. Penso che quello integrato in Visual Studio ti mostri anche l'asm, e sia comodo da utilizzare (mai usato per asm inline, ma penso funzioni).
Mal che vada puoi usare un altro debugger esterno, tipo x32dbg (quello che sto usando io).

Errori come questi (il fatto che non incrementi EBX) li becchi subito perchè vai step by step e vedi che la lettera considerata è sempre la medesima.
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Dunque sei in windows e usi masm incluso in visual studio. Per il debug usavo ollydbg, carino.

Si, talvolta lo uso ancora anche io. In questo caso può anche farlo, normalmente meglio x64dbg, che dispone anche del debugger x64 (x32dbg appunto).

Il suo codice ha sicuramente come target x86 in quanto asm inline è supportato solo nel 32bit (o almeno così era sino a poco tempo fa).
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!