IDD Personalausweis Prüfziffer berechnen in nasm



  • Hi, 🙂
    Ich möchte ein Programm schreiben (in asm nasm), das mir die Letzte Zahl der Ausweis Nummer berechnet.Sozusagen gibt man die ersten 9 zahlen in die komando Zeile ein und bekommt dann als Ergebnis die letzte Prüfziffer für das alter. 😕
    Wie man diese Zahl raus bekommt ist ganz einfach man multipliziert jede einzelne zahl des Ausweises nacheinander mit 7,3,1 und summiert diese. In der Theorie alles ja ganz einfach aber in der praxis ??? 😮 😮
    Hat jemand vielleicht einen Ansatz für mich oder Tipps mit was ich anfangen sollte/brauche.
    Danke für eure Zeit ❤



  • Stern.chen22 schrieb:

    In der Theorie alles ja ganz einfach aber in der praxis ??? 😮 😮

    Die Praxis ist noch viel einfacher.
    (Welches Problem hast du denn nun genau, und welche Hardware, welche Betriebsysteme oder welche Programmiersprachen zur Verfügung?)



  • nachtfeuer schrieb:

    Stern.chen22 schrieb:

    In der Theorie alles ja ganz einfach aber in der praxis ??? 😮 😮

    Die Praxis ist noch viel einfacher.
    (Welches Problem hast du denn nun genau, und welche Hardware, welche Betriebsysteme oder welche Programmiersprachen zur Verfügung?)

    Also ich mache das ganze in der VM 32 Linux mint und zwar in Assembler bzw nasm.
    Meine Frage ist eher ich weis nicht so richtig wo ich anfangen soll, muss ich als erstes die Buchstaben die evtl manchmal auch in der Ausweisnummer vorhanden sind in integer umwandeln? oder soll den eingegeben code erstmal auf den stack pushen?



  • Ich habe keine Ahnung, wie die Prüfsummen berechnung funktioniert (also, in welche Zahlen du die Buchstaben umrechnen willst usw.) und das ich das letzte mal Assembler selbst geschrieben habe kann auch schon 10 Jahre her sein, aber wie wäre es mal mit ausprobieren? Du stellst schon fest, welche Herangehensweise die bessere ist.

    Für mich klingt es erstmal Sinnvoll, die Eingabe aus den Stack zu pushen. Zumal du den dann für die Prüfsummenberechnung einfach Rückwärts zurück poppen kannst und dabei schön sequentiell alles abarbeiten können müsstest.



  • Es ist ja an wenig netter für den Anfang wenn man sequentiell über Register abarbeitet, also z.B. mul cl/ mul ch + logische Operationen und Summieren usw. aber wäre auch eine nette Übung, sich die SSE* usw. Möglichkeiten mal genauer anzuschauen.
    (*z.B. logische Operationen mit > 128 Bit..)

    (Interessant wäre natürlich auch, das Programm in C/C++ zu schreiben und sich die Optimierungen/Assemblerlistings anzuschauen..)

    ..oder Spaß mit LEA usw.. 😉



  • Hab jetzt mal einfach mal was versucht was irgendwie noch nicht ganz hingehauen hat hab mal daneben im code meine fragen auf deutsch geschrieben vllt wenn jmnd eine antwort hat danke & danke jetztigen hifen. 🙂

    global main
    extern printf
    extern atoi
    
    section .data
    
    msg: db "IDD Number: %s",0 ; zb. LF45PK773    Wo wird dieser String gespeichert in welchem register eax? ebx? ebp?
    end: db "Your Number is: %d",10,0 ; Result (9 for this example) Ausgabe der prüfziffer 
    
    section .bss
    
    Variable1: dd 7  ; die variablen 7 3 1 um sie später zu mutliplizieren 
    Variable2: dd 3
    Variable3: dd 1
    
    section .text
    
    main:
    mov ebx, [esp+0x08] ; typed string to EBX    String in ebx moven
    push dword [ebx+0x04] ; push it on the stack 
    call atoi ; Form the String to an Integer    String in Integer umwandeln aber wie wandle ich Eingegebene Buchstaben in Ascii code um um diese später multiplizieren zu können 
    add esp, 4
    
    call Subprogramm:
    
        push msg        ; our string Unsere msg pusheh für die ausgabe
        call printf     ; ausgeben der msg 
        add esp, 4      ; stack reparieren um 4
    Ausgabe:
        push end        ; end pushen
        push eax        ; ergebnis pushen
        call printf     ; ausgeben
        add esp, 8
        ret
    
    Subprogramm: ; Unterporgramm
    
    ;First Digit  Erste ziffer des eingegbenen strings
    ; Zeichenkette vom stack nehmen um die zahlenfolge zu trennen also div durch 10 um dann um dann den errechnete zahl auf eax zu moven und die rest zahl bleibt in edx
    
    pop ebx     ; take the changed string to integer from the stack 
    mov edx, ebx  ; move ebx to edx
    mov eax , 10  ; put in eax 10
    div eax       ; edx:eax ---> edx:10 saves the result in eax the rest is in edx
    
    movzx ebx, Variable1    ; erste Zahl mal 7 und auf den stack pushen bzw Wo das ergebnis speichern/ aufbewahren um für die spätere addition zu benutzten????
    mul ebx       ; eax*ebx 
    push eax      ; Ergebniss in eax speichern ??? bleibt es dort wird es überschrieben im nächsten befehl? 
    
    ;Second Digit / Zweite ziffer das selbe nochmal nur dann multipliziert mit 3 und aufbewahren????
    pop ebx     ; take the changed string to integer from the stack
    mov edx, ebx  ; move ebx to edx
    mov eax , 10  ; put in eax 10
    div eax       ; edx:eax ---> edx:10 saves the result in eax the rest is in edx
    
    movzx ebx, Variable2
    mul ebx       ; eax*ebx
    push eax
    
    ;Third Digit / dritte ziffer der zeichen folge wieder das selbe und dann multipliziert mit 1
    pop ebx     ; take the changed string to integer from the stack
    mov edx, ebx  ; move ebx to edx
    mov eax , 10  ; put in eax 10
    div eax       ; edx:eax ---> edx:10 saves the result in eax the rest is in edx
    
    movzx ebx, Variable3
    mul ebx
    push eax
    
    JMP Subprogramm ; Go back again and do the same from the beginning (loop)   / und jetzt das selbe von vorne also mit der 4ten ziffer wieder mal 7 dann 5te mal 3 usw 
    
    ;NOW add all digits together / Nun alle miteinander Addieren aber wo wurden sie gespeichert ? alle einzelnen Ergebnisse???
    pop eax
    add eax    ; ???
    ret
    
    JMP Ausgabe ;/ gehe wieder zur main ausgabe um die errechnete prüfziffer auszugeben
    


  • Das sieht doch für einen ersten Einstieg schon recht ordentlich aus.

    Der ein oder andere Flüchtlings Flüchtigkeitsfehler versteckt sich noch hier und da.

    1. Es wird grundsätzlich bzw. immer implizit durch eax geteilt.
    2. du willst ja Mod 10 haben
    2a) das geht hier mit einer logischen Operation besser/schneller/eleganter:
    AND AL "0F" also 00001111 - fertig
    2b) bei Wort - bzw. Bytegrößen geht die Division mit Rest über AH und AL (der Rest in AL).
    (2 c puristique: hier auch mit BCD-Zahlen herummachen, falls interessiert.)

    3. Extra mit 1 multiplizieren braucht man gar nicht.

    4. in dem Assemblertutbuch ("Programming from the Ground Up") von Jonathan Bartlett ist ein kleiner praktischer Handzettel für den GDB.

    5. Einleseroutinen für Strings platzieren diese in aller Regel in den Speicher, aber Repetierbefehle benutzen u.a. Si und Di zum Indexieren (deswegen + x + y usw. mit LEA -> z.B. mehrdimensionale Tabellenanlagen.
    Mit DB oder DW werden in aller Regel Zeichenketten codiert, die im Speicher abgelegt werden, genau wie der Assemblercode bzw. kann die Zeichenkette genau das sein (-> Hexeditor).