2017-12-15 17 views
-2

für eine beliebige Anzahl in der Basis 10 an die Basis 16 umzuwandeln, eine gute Umsetzung wäre:x86 Eingang eine Zahl in der Basis 2 und gibt es als Zahl zur Basis 8

segment data use32 class=data 
    number dd 0 
    format_input db "%d", 0 
    format_output db "%x", 0 

segment code use32 class=code 
start: 
    push dword number 
    push dword format_input 
    call [scanf] 
    add esp, 4*2 

    push dword [number] 
    push dword format_output 
    call [printf] 
    add esp, 4*2 

Gibt es eine Implementierung gleich für die Umwandlung einer Zahl von der Basis 2 auf die Basis 8?

+3

Das heißt nur C-Bibliothek Funktionen aufrufen, das ist nicht "Umsetzung" der Konvertierung. Wenn das für dich genug ist, gibt es für Oktal den Formatierer '% o'. Für binäre .. überraschend sehe ich keine, also müssen Sie Ihre 'scanf'-Dokumentation überprüfen, ob es einige hat, oder schreiben Sie Ihre eigenen. Aber nichtsdestoweniger, das ist ziemlich elementar, Sie sollten in der Lage sein, jede Basis zu jeder Basis auf Papier + Stift leicht zu konvertieren, wenn Sie die Mathematik hinter Zahlensystemen verstehen. Dann ist es normalerweise trivial, solche Berechnungen in Assembler zu schreiben, besonders wenn zwei Basen beteiligt sind, müssen Sie nur die Bitwerte neu anordnen. – Ped7g

+0

I.e. Eingang in Basis 2 hat 1 wichtiges Bit pro Eingabeelement (wenn es ASCII-String wie "010101" ist, dann können Sie von jedem Zeichen alle Bits außer dem niedrigsten ablegen, und das ist Ihr Binäreingang, ASCII ''0'' ist' 0011_0000' und "1" ist "0011_0001", so dass die letzten Bits eines solchen String-Eingangs 0, 1, 0, 1, 0, 1 ... sind.und die Ausgabe in Oktal benötigt 3 Bits pro Ziffer, so dass Sie diese nur in "010", "101" gruppieren und diese zwei Werte, d. h. "25", ausgeben müssen. ... keine Division/Multiplikation erforderlich (im Gegensatz zur Formatierung der Basis 10, wo eine Art Multiplikation/Division stattfinden wird). '0b010101 == 0o25' – Ped7g

+2

@ Ped7g: ISO C scanf/printf [habe keine Basis 2 Conversion-Spezifizierer] (https://stackoverflow.com/questions/11597863/why-does-scanfi-a-not-take- binary-like-0b101), und es ist keine Standard-Erweiterung, [nicht einmal in glibc] (https://stackoverflow.com/a/112947/224132). Für die Eingabe nimmt 'strtol' jedoch ein Radix als Argument an. –

Antwort

1

Dies ist essentially a duplicate of this C/C++ question, weil Sie fragen, wie Sie es tun, indem Sie C-Bibliotheksfunktionen aufrufen. Das ist in Ordnung, kein Grund, warum du das nicht in asm machen kannst. Ich entschied mich, nicht einfach als Duplikat zu schließen, weil es genug gibt, um zu sagen, wie man es richtig macht, dass es ein bisschen lang ist für nur einen Kommentar.

C-Syntax ist ein einfacher Weg, um auszudrücken, welche Funktionen Sie zusammenkleben müssen, so werde ich im Grunde nur in C beantworten. Wenn Sie einen der Schritte mit einer Schleife in Asm tun möchten, gehen Sie dafür. Konvertieren einer binären Zeichenfolge in Ganzzahl ist sehr einfach, Sie nur Ziffern einzeln umschalten. (Oder verwenden Sie SSE2 pmovmskb).


Verwenden einer printf %o Umwandlung für die Ausgabe in der Basis 8; das wird direkt von ISO C unterstützt.

Base 2 isn't, though. Aber strtoul konvertiert Strings -> vorzeichenlose Ganzzahlen mit Ihrer Wahl von Radix. Das einzige verbleibende Problem ist das Lesen der Eingabe als String. Es gibt viele Möglichkeiten, dies zu tun. Wenn Sie jedoch vermeiden möchten, dass Zeichen, die nicht Teil einer Basis-2-Nummer sind, nicht gelesen und verwendet werden, können Sie scanf mit einer %[]-Umwandlung verwenden, die nur die Zeichen 0 und 1 akzeptiert.

So können Sie asm schreiben, die wie folgt aussieht:

// optionally this buffer could be static like your `number`, but there's no reason to do that. 
char buf[65];  // reserve 65 bytes on the stack with sub esp, 80 (rounded up to keep stack 16B-aligned) 

buf[0] = 0;  // NULL terminate our stack buffer to avoid crashing in strtoul if scanf doesn't convert anything. 
int success = scanf(" %64[01]", buf); // skip optional whitespace and store up to 64 bytes + null terminator into buf 
// optional: check the conversion. 

unsigned long num = strtoul(buf, NULL, 2); // parse as base 2, returning a binary integer 

printf("%lo\n", num);   // print as octal 
// or %o if int and long are the same width in 32-bit asm 

dieser C-Anweisungen können alle mit einem kurzen Block von asm-Anweisungen implementiert werden, nicht Schleifen. Wenn Sie nicht sicher sind, wie, ask a compiler with gcc -O2 -S -masm=intel.

Beachten Sie die Längenbeschränkung in der Formatzeichenfolge scanf, so dass Sie keinen Pufferüberlauf haben, wenn der Benutzer einen Schlüssel gedrückt hält und Ihr Programm 1000 Byte 1 liest.

Beachten Sie auch die führenden Leerzeichen in der Formatzeichenfolge, um Whitespaces im Puffer stdin zu überspringen. (z.B. die Zeilenschaltung am Ende der vorhergehenden Zeile, die scanf normalerweise nicht verbrauchen wird). Conversions like %c and %[ don't skip leading whitespace on their own.

Verwenden Sie %64s, wenn Sie nachfolgende nichtstellige Zeichen verwenden möchten. strtoul stoppt beim ersten Zeichen ohne Ziffern. (Und einen Zeiger auf diese Position speichern, wenn Sie einen Nicht-Null char ** als 2. Arg übergeben.)

Verwandte Themen