Finden Zahl ist gerade/Ungerade-in Montage
Ich versuche zu finden, ob eine gegebene Zahl (Eingabe durch Anwender) gerade oder ungerade ist.
Ich bin einfach die Anwendung
AND
operation auf binären Ziffern ein Nein. mit1
, Wenn die Zahl ungerade ist, dann wird der Betrieb infolge0
und wir werden die Ausgangs-Zahl ist ungerade, sonst werden wir die output-Nummer ist auch.
Obwohl die Logik scheint einfach, Aber es funktioniert nicht in der code unten. Ich bin nicht immer, wo ist das problem im code. Kann mir jemand sagen, wo ist das problem
section .data
userMsg db 'Please enter a number'
lenuserMsg equ $ - userMsg
even_msg db 'Even Number!'
len1 equ $ - even_msg
odd_msg db 'Odd Number!'
len2 equ $ - odd_msg
section .bss
num resb 5 ;Reserved 5 Bytes for Input
section .text
global _start ;must be declared for linker (gcc)
_start:
;User Prompt
mov ebx, 1 ;file descriptor (stdout)
mov ecx, userMsg ;message to write 'Please enter a number'
mov edx, lenuserMsg ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
;Taking user input
mov ebx, 0 ;(stdin)
mov ecx, num
mov edx, 5 ;i/p length
mov eax, 3 ;system call number (sys_read)
int 0x80 ;call kernel
mov ax, [num]
and ax, 1
jz evnn ;Jump on Even
;Printing No. is Odd
mov ebx, 1 ;file descriptor (stdout)
mov ecx, odd_msg ;message to write 'Odd Number!'
mov edx, len2 ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
jmp outprog ;Jump to exit
;Printing No. is Even
evnn:
mov ebx, 1 ;file descriptor (stdout)
mov ecx, even_msg ;message to write 'Even Number!'
mov edx, len1 ;message length
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
;Exit
outprog:
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
- Nur so ein Gedanke -- (habe ich nicht programmiert asm seit über 30 Jahren), aber sind Sie sicher, dass die Eingabe num wird gesehen als eine Zahl? z.B. bekam ich SELTSAM für eine Eingabe der Buchstaben 'a' das ist der ascii-65.
- Ja, die Prüfung der niedrigen bit einer Zahl ist richtig, denn Sie sind gespeichert in base2. Ihr Programm könnte kompakter sein, wenn Sie Ihre gerade/ungerade Zweig setzen Sie einfach den Zeiger und die Länge, ohne duplizieren der rest der
int 0x80
system nennen. Sollten Sie kommentieren Sie Ihren code mit mindestens den symbolischen Namen für die system-call-Nummern (z.B.sys_write
). - Sie können die Tatsache, dass die Anzahl der Zeichen Lesen von der Eingabe wird zurückgegeben, in
eax
aus sys_read. Ein hack wäre, um die Anzahl der Zeichen zurückgegeben, wie ein index, um die richtige zu finden die meisten ASCII-Ziffer. Die Anzahl der Zeichen zurückgegeben, gehören die Abbruch-Zeichen (0x0a). Dies könnte durch den Austauschmov ax, [num]
and ax, 1
mitmov al, [num+eax-2]
and al, 1
. Dies setzt Voraus, dass der Puffer ist groß genug, um die längste Zahl die einschließlich des abschließenden Charakter. - Wenn Sie beabsichtigen, Sie zu tun, alle anderen arbeiten mit zahlen (neben der gerade/ungerade) - Eingabe von der Konsole aus, werden Sie wahrscheinlich benötigen, um zu konvertieren der Zeichenfolge zurückgegeben, in eine ganze Zahl, und arbeiten, die auf die ganze Zahl.
- Es ist sehr ratsam, Kommentar in Ihren code ein. Es wird helfen, jemand nicht vertraut mit den jeweiligen system-call-Nummern Hilfe zu leisten, ohne dass die Forschung die Plattform, die Sie sind auf. Es wird auch Ihren eigenen Debuggen viel einfacher.
- Ich habe kommentiert den code bitte haben Sie einen Blick.
- Michael Petch bereits vollständig beantwortet Ihre Frage mit seinen Kommentaren. Beachten Sie, dass wie belwood darauf hingewiesen, dass der ASCII-Wert des letzten Zeichens wird das Gegenteil odd/Ebenheit, die aus der Ziffer codiert wird.
- statt
AND
ing mit 1 Sie können nurtest
, die nicht zerstören, die Quelle registrieren und ist effizienter
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dein code nicht funktionieren, weil, wenn Sie Fragen den Benutzer nach einer Zahl, die Sie Lesen, in eine ASCII-codierte string. Sie rufen
atoi
(ASCII in INT) zuerst konvertieren den string in eine "echte" Zahl, die als Computer sehen.atoi
enthalten ist in glibc.Können Sie auch noch ein wenig testen, auf das am wenigsten signifikante bit (bit 0), um herauszufinden, ob es gerade oder ungerade ist:
Was BT hat, es kopiert die bit-zu-CF-ist, und Sie können bedingte Sprünge, die Grundlage.
test al, 1
/jnz
funktioniert genauso, hat aber etwas kleinere code-Größe, und ist etwas effizienter (test/jnz können makro-Sicherung in einem einzigen test-und-Zweig-uop, im Gegensatz zu BT).bt r, r/i
ist effizient, aber: nur eine uop (im Gegensatz zu einem Speicher-Operanden für die ersten arg, in welchem Fall es ist viel langsamer als TEST auf einem memory-arg, weil das crazy-CISC-bitstring Semantik, wo der bit-index wirkt sich auf die Speicher-Adresse).'0'
ist 0x30, können Sie einfach testen, das low-bit des letzten ASCII-Zeichen des Strings. Sie brauchen nicht zu nennen, atoi, es sei denn, Sie brauchen, um zu testenn % 3
oder andere Modul, dass nicht ein Faktor 10. (d.h. können Sie testenn % 2
,n % 5
, undn % 10
durch die Betrachtung nur die Letzte Ziffer).Konzentrieren Sie sich nur auf das eigentliche problem bei der hand ist, sollen wir? Wenn Sie sagen, eine ASCII-char in AL-register, nur schalten Sie ihn in eine Stelle, und der rest sollte einfach nur natürlich sein. In computing (Binär-zahlen und-Systeme), Ganzzahlen Seltsamkeit oder Ebenheit wird bestimmt durch das bit 0. Wenn es 1 ist, ist es eine ungerade Zahl ist. Wenn er 0 ist, ist es eine gerade Zahl ist. (Ich bin überrascht, dass niemand hat speziell genügend Wert auf diese so weit).
sub al, 30h
hat keinen Einfluss auf das low-bit, so dass Sie nicht brauchen, um es zu tun, bevor die Prüfung der low-bit. (Auchtest al, 1
ist effizienter als SHR, und nicht zerstören den Wert.)test al,1
statt-eine Verschiebung, obwohl. Nachdem die Zahl um danach, ohne zu tun, eine langsamercl al, 1
wiederherzustellen, ist es sinnvoll, und test/jnz können makro-Sicherung auf Intel/AMD-CPUs.) Ich glaube, ich war einfach nur genervt, dass diese Antwort hatte ein upvote, aber mein umfassendere Antwort (die sagt, das und mehr) nicht, das ist ein bisschen albern von mir. Ihre Antwort hat mich zu aktualisieren mine, um die wichtigen Punkte klar werden.mov ax, [num]
lädt die ersten 2 Ziffern der Benutzer die Eingabe-Zeichenfolge, und Sie sind Tests, die der ersten ein. Du bist also tatsächlich prüfen, ob das erste Zeichen ist der ASCII-code ist auch.2 ist um den Faktor 10, so brauchen Sie nur zum testen der low-bit der letzten Nachkommastelle zu bestimmen, ob eine base-10-Zahl gerade oder ungerade ist.
Und da der ASCII-code für
'0'
ist 0x30, können Sie einfach testen, das low-bit des letzten ASCII-Zeichen des Strings.Brauchen Sie nicht zu rufen
atoi()
es sei denn, Sie brauchen, um zu testenn % 3
oder andere Modul, dass nicht ein Faktor 10. (d.h. können Sie testenn % 2
,n % 5
, undn % 10
durch die Betrachtung nur die Letzte Ziffer). Beachten Sie, dass Sie nicht nur testen Sie die niedrigen 2 bit des low Nachkommastelle zu prüfen, um ein Vielfaches von 4, denn 10 ist nicht ein Vielfaches von 4 ist. z.B.100%4 = 0
, aber30%4 = 2
.So, da ein Zeiger + Länge, die Sie verwenden können
TEST byte [last_char], 1
/jnz odd
. z.B. nach Ihrem sys_read, müssen Sie einen Zeiger auf die Zeichenkette in ECX, und der Rückgabewert (Anzahl Bytes) im Register EAX.Dann kommt der eigentliche test für gerade/ungerade: Nur ein test&ast, auf dem letzten ASCII-Ziffer: