Τρίτη, 17 Μαΐου 2016

Αναθεώρηση 18 (Union σε Structures)

Σε αυτή την αναθεώρηση διόρθωσα και bug (άρα καλό είναι να κατεβάσει κανείς την τελευταία έκδοση).

Πρώτο παράδειγμα με την νέα λειτουργία Union. Η ένωση σημαίνει ότι την ίδια μνήμη μπορούμε να την προσεγγίζουμε με διαφορετικές "μεταθέσεις" από την αρχή (offsets), και σε κάθε περίπτωση να έχουμε δώσει και το τύπο αυτού που περιλαμβάνεται εκεί.
Δεν γράφουμε την λέξη Union, απλά όταν δει την λέξη structure (μπορούμε να ονομάσουμε την αρχή, για να ξεχωρίζουν τα ονόματα αν είναι ίδια τα εσωτερικά με τα εξωτερικά) ή μια αρχή μπλοκ ο διερμηνευτής τότε ξέρει ότι έχει Union. Αν θέλουμε τριπλό τότε πρέπει τα δυο πρώτα μέρη να είναι σε μπλοκ

structure alfa {
           {
                  low as integer
                  high as integer
            }   
            value as long
}

Buffer Clear one as alfa *100
Return one, 20!Value:=0xFFFFAACC
Hex Eval(one, 20!high),"", Eval(one, 20!Low), "",Eval(one, 20!value)

Στο παράδειγμα παραπάνω έχουμε ορίσει το alfa να το διαβάζουμε και σαν long (unsign long) και σαν integer (unsign integer) από τα δυο μισά. Η εντολή Hex είναι η Print αλλά για δεκαεξαδικό (unsign, όπου βρει αρνητικούς ή μεγαλύτερο από 0xFFFFFFFF τότε εμφανίζει αντί για αριθμό ένδειξη λάθους --- ή +++). Δείτε ότι το High όχι μόνο του λέει πόσο  θα μετατεθεί από το 20 *4 που είναι η μετάθεση από την θέση του πρώτου ψηφίου (Byte) αλλά και το μέγεθος που θα πάρει, εδώ τον ακέραιο των 2 Bytes (ψηφίων).

Τι θα γίνει όμως αν βάλουμε κάτι πίσω από το Value (ενώ τώρα Value και Low είναι ίδιες μεταθέσεις, δείχνουν στο 0)

Για να γίνει πιο ωραίο, βάζουμε το value ως πίνακα 20 long (Μακρύς). Τα μέρη που απαρτίζουν την ένωση, "ξεχειλώνουν" όσο το μεγαλύτερο. Όμως στο πρώτο μέρος, με τα Low και High έχουμε μεταθέσεις από την αρχή. Πώς θα βρούμε ας πούμε το 3 στοιχείο. Και αν υποθέσουμε ότι έχουμε 100 από το alfa, τότε ας βάλουμε στόχο να βρούμε το alfa[10]high[3], alfa[10]low[3], alfa[10]Value[3].
Εδώ το πρόβλημα λύνεται με μια συνάρτηση! το Value[3] έχει μεν το 3 αλλά αυτό δεν είναι καθαρός αριθμός, έχει μονάδες, έχει το Long το οποίο είναι 4*byte. Και το low[3] έχει και αυτό μονάδες είναι το Integer ή το 2*byte. Για να λειτουργήσει εδώ σωστά η μετάθεση πρέπει για κάθε πραγματική μετάθεση στο value να έχουμε ισοδύναμη στο low, και ομοίως και στο high. Αν είχαμε Long στο παράλληλο, ή κατ΄ένωση μέρος, τότε θα ένα προς ένα ισοδυναμία. άρα το 3 στο ένα και το 3 στο άλλο θα ήταν ταυτόσημα. Τώρα χρειάζεται η συνάρτηση Mult() που μας δίνει το νούμερο για πολλαπλασιασμό. Αυτό βγαίνει από την αναλογία, 4 προς 2 και έτσι μας δίνει τον παράγοντα 2 που πολλαπλασιάζουμε στο 3 στο Low. Το 30!high!mul*M g είναι στην ουσία:
To M=3 επειδή ζητάμε το 4o στοιχείο (στο 0 είναι το πρώτο)
Δείκτης βάσης+30*μέγεθος(alfa)+μετάθεση(high)+μέγεθος(high)*2*3
Ο τύπος στο mult() δεν είναι γενικός. Μας βολεύει εδώ γιατί το μέγεθος 4 που επαναλαμβάνεται είναι το άθροισμα του μήκους σε bytes (bytes) των δυο ακεραίων (integer), και τόσο είναι και το μήκος του μακρύ ή long στο δεύτερο μέρος (και τα δυο μέρη δείχνουν την ίδια μνήμη, ο τρόπος που διαβάζεται και γράφεται έχει να κάνει με την χρήση του offset, ή μετάθεσης). Αν βάζαμε στο low as integer πολλαπλασιαστή έστω 20 τότε αντί να έχουμε το high ακριβώς 2 Byte μετά θα το έχουμε 2*20, ή 40 byte μετά. Αν μάλιστα στο long δεν βάζαμε το *20 αλλά το βάζαμε στο high, τότε και το value θα ήταν εκ των πραγμάτων  *20 εκτός να προσθέταμε και κάτι άλλο.



structure alfa {
            base1 as integer*30
           {
                  low as integer
                  high as integer
            }   
            \\ now we extend to 20 items as Long or High-Low integers
            value as long*20
}
Buffer Clear one as alfa *100
Return one, 20!Value:=0xFFFFAACC
Hex Eval(one, 20!high),"", Eval(one, 20!Low), "",Eval(one, 20!value)
N=10 \\ is a multiplier alfa
M=3 \\ is a multiplier  Long
\\ offsets maths
\\ we use a multiplier based on the ratio
\\ value is long (4 bytes)
\\ if we make low as byte and high as byte then we use mult(4,1)
def mult(From1, to1)=From1 div to1
mul=mult(4,2)
Return one, N!Value!M:=0xFF1FA5BB
HEX Eval(one, N!high!mul*M),"",Eval(one, N!low!mul*M), "",Eval(one, N!value!M)
\\ offsets
Print alfa("high"),alfa("low"), alfa("value"), alfa("base1")
\\ real pointer
Print one(0), one(4)-one(3)=len(alfa)
Print Len(one) \\ 14000 bytes



Να κάτι πιο "χοντρό"....
structure alfa {
           structure beta {
                  low as integer
                  high as integer
            }  
            structure delta {
                  low as byte
                  middle1 as byte
                  middle2 as byte
                  high as byte
            }   
            value as long
}
\\  len in bytes, number of offsets
Print len(alfa), len.disp(alfa)
For i=0 to len.disp(alfa)-1
      \\ print names and offsets  and length of offsets
      Print format$("{0:20} {1::4}{2::4}", eval$(alfa, i), eval(alfa), alfa(eval$(alfa, i)))
next i


Structure beta {
      aname as integer *50
      one as alfa*2
}
Buffer Clear alfa1 as alfa, alfa2 as alfa*2


Print len(alfa1), len(alfa2)
Buffer Clear kappa as beta*100
\\ len in bytes (10800), number of parts (100)
Print Len(kappa), Len.disp(kappa)
Return alfa1,0!delta.middle1:=0xFF
Hex eval(alfa1,0!value)
Return alfa1,0!delta.high:=0xFF
Hex eval(alfa1,0!value)
Return alfa2,1:=eval$(alfa1) \\ make a copy
Return kappa, 24!one!1:=eval$(alfa1)
\\ offset here is in bytes
Hex eval(kappa, 24*len(beta)+beta("one")+len(alfa)*1+alfa("beta.high") as integer)
\\ offset here is in item len, 24 for (beta) and for item one 1 for (alfa)
\\ because alfa has 4 bytes automatic return long
Hex eval(kappa,24!one!1)
Return kappa, 24*len(beta)+beta("one")+len(alfa)*1+alfa("delta.middle2") !:=0x33 as byte
Hex eval(kappa,24!one!1)
hex eval(kappa, 24*len(beta)+beta("one")+len(alfa)*1+alfa("delta.middle2") as byte)