Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: FalShen am 25. October 2006, 21:54
-
Yay, ich bin's wieder, der noob... Is' seltsam, aber ich krieg offenbar nix hin. Vllt könnt ihr mir wieder helfen, wäre sehr nett. Ihr könnt mich auch auslachen...
Ich will ne beliebige 32-bit Zahl ausgeben. Eine einzelne Ziffer hab ich schon, aber wenn ich diesen code ausführe, kriege ich immer nur eine '1' als ausgabe. Bochs Debug bringt mir nix, da ich da nicht mehr durchsehe.
void printnum(_u32 n)
{
_u32 num = n;
if(num == 0) putch('0');
else
{
for(i=9;i>=0;i--)
{
_u32 exp = 10^i;
if(num >= exp)
{
_u8 d = num / exp;
putdigit(d);
num -= d * exp;
}
}
}
}
Hoffe ihr könnt mir noch einmal helfen...
PS: Sollte ich eine printf-funktion schreiben oder mich lieber von einer Klippe stürzen?
-
:-D Das mit der Klippe is ne ganz schlechte Idee.
Wenn du schon ne Funktion für eine einfach Stringausgabe hast, guck dir das mal an:
void PrintDec(long num)
{
char buffer[11];
int i = 10;
do
{
buffer[--i] = '0' + (char)(num % 10);
num /= 10;
} while (num > 0);
buffer[10] = '\0';
Print(buffer + i);
}
Früher oder später ist aber eine richtige printf-Funktion, sehr hilfreich.
-
einen kleinen Fehler seh' ich: das
if (num >= exp)
verhindert nicht nur die Ausgabe führender Nullen, sondern so wie ich das sehe auch jede weitere Null in der Mitte der Zahl.
Die meisten Implemtierungen sehen ungefähr so aus (das hier ist natürlich nicht getestet^^):
void printnum (int n)
{
char tmp[20];
int i = 0;
if (n == 0) printch('0');
else
{
while (n > 0)
{
tmp[i++] = '0' + n % 10;
n = n / 10;
}
while (i-- > 0)
{
printch(tmp[i]);
}
}
}
Und wegen dem printf()... es erleichtert die Ausgabe enorm, und so viel Aufwand ist das auch nicht, zumindest wenn man nur %d und sowas unterstützt und keine zusätzlichen Format-Angaben zwischen % und d.
Aber falls du C++ benutzt, könntest du noch einen Schritt weiter gehen und einen Stream basteln mit überladenem "<<"-Operator und so. Wenn man sich in die Syntax für Operator-Überladungen erstmal herreingefunden hat, sind die wirklichen Routinen sogar einfacher (kein printf, sondern nur eine Überladung für int, einen für uint, etc...).
Aber printf oder stream is wohl Geschmacksfrage :)
edit: da war jemand schneller mit'm schreiben :-D
-
_u32 exp = 10^i;
Da kennt einer wohl seine Programmiersprache nicht 8-) Das ist keine gute Voraussetzung :-D
Das "^" ist nämlich keine Potenz, sondern ein exklusiv oder :wink:
Insofern würd ich die Zahl rückwärts in einem String speichern (einfach immer den Rest von einer Division durch 10 in den String) und dann mit dem Ergebnis der Division genauso fortfahren. Danach den String umdrehen und dann erst ausgeben.
*lol* richtig was los heute
-
@DarkThing, bei dir wird die Zahl falsch herum ausgegeben.
-
Ich habs jetzt nochmal getestet und die Zahl wird richtigrum ausgegeben...
Dieser Code gibt jedenfalls 123 aus.
#include <iostream>
using namespace std;
void PrintDec(long num)
{
char buffer[11];
int i = 10;
do
{
buffer[--i] = '0' + (char)(num % 10);
num /= 10;
} while (num > 0);
buffer[10] = '\0';
cout << buffer+i << endl;
}
int main(int argc, char *argv[])
{
PrintDec(123);
return 0;
}
Ich fülle ja den Buffer von hinten nach vorne, sozusagen. i wird mit 10 initialisiert und dann immer kleiner.
-
ups sry, das hab ich ganz übersehen :oops: Trotzdem ist das nicht unbedingt die portabelste Lösung :lol:
-
Danke Leute!
Dass mit dem stream werde ich mir noch mal überlegen... Würde so was gerne auf OS ebene machen, wenn es überhaupt möglish ist...
Vielen dank noch mal...
-
Kannst dir bei meinem OS anschauen. Ich versuch es kompatibel mit dem C++ Standard zu halten. Beteiligte Sourcedateien:
* libc++/ios (https://opensvn.csie.org/traccgi/lightOS/browser/trunk/lib/libc%2B%2B/include/ios)
* libc++/ostream (https://opensvn.csie.org/traccgi/lightOS/browser/trunk/lib/libc%2B%2B/include/ostream)
* libc++/iostream (https://opensvn.csie.org/traccgi/lightOS/browser/trunk/lib/libc%2B%2B/include/iostream)
* kernel cout/etc. Implementation: kernel/libc++/iostream.cpp (https://opensvn.csie.org/traccgi/lightOS/browser/trunk/kernel/libc%2B%2B/iostream.cpp)
* userspace cout/etc. Implementation: lightOS/x86/iostream.cpp (https://opensvn.csie.org/traccgi/lightOS/browser/trunk/lib/lightOS/x86/iostream.cpp) (Ist noch durch nen kernel syscall gelöst, aber das wird sich ändern)
-
Ich musste das ganze in Assembler schreiben... Aber... der sagt mir nur 'Division by Zero Error'...
putnum:
cmp ebx, 0
jz putzero
mov edi, tempstr
mov [n], ebx
putnum1:
mov eax, [n]
mov bx, 10
div bx
mov eax, '0'
add eax, edx
stosb
mov eax, [n]
mov bx, 10
div bx
mov [n], eax
cmp eax, 0
ja putnum1
mov esi, tempstr
call write
jmp putnum_end
putzero:
mov al, '0'
call putch
jmp putnum_end
putnum_end:
ret
Also, ich hab ja nur mov bx, 10
div bx drin... wo is da eine division mit null?
-
Erst ma
DIV BX
teilt nicht EAX durch BX sondern DX:AX durch BX
Das ergebniss steht dann in AX
der Divisions-Rest in DX
Wenn das ergebniss zu groß für AX ist, wird glaub ich auch ein Divisions fehler ausgelöst(~> Division durch null))
um das zu verhindern probier ma
XOR EDX, EDX
MOV EAX, [n]
MOV EBX, 10
DIV EBX
teilt EDX:EAX durch EBX
ergebnis in EAX
rest in EDX