PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Taschenrechner mit 4KB - c0derz Aufgabe von früher



pav0c
03.02.2018, 20:31
Hey Leute,

ich weiß nicht ob von euch noch jemand c0derz kennt, doch ich habe mich daran erinnert, dass es damals eine Art Challenge gab:
Und zwar sollte man einen Taschenrechner programmieren der so klein wie möglich ist. Soweit ich weiß, hat es jemand geschafft einen mit nur 4KB hinzubekommen!
Weiß noch jemand wie das geht? Ich weiß noch, dass man in den Projekteinstellungen bei Visual Studio etwas einstellen musste :D

Hoffe mir kann jemand weiterhelfen.


Vielen Dank und Grüße



PS: Ist noch jemand von damals aktiv? f0gx z.B. :D

gORDon_vdLg
03.02.2018, 21:20
Das müsste gehen indem du Code schreibst welchen du nicht gegen irgendeine Lib linkst, also auch nicht die C Standardbibliothek. Kann sein dass das mit der Linkeroption /NODEFAULTLIB geht, habs jetzt nicht getestet, klingt aber danach. Bin auch kein Visual Studio Pro-Gamer. Diverse C Standardfunktionen kannste dir trotzdem z.B. aus der msvcrt.dll laden. Wenn GUI dann natürlich auch ohne irgendwelche Libs mit reiner Winapi.

sontyp
04.02.2018, 01:10
Schreibs in Assembler ;-P

Cystasy
04.02.2018, 10:05
Javascript:


function add(a,b){return (a+b)}
function sub(a,b){return (a-b)}
function div(a,b){return (a/b)}
function mul(a,b){return (a*b)}


Das sind die 4 Grundrechenarten.. das sind im ganzen 127 bytes. Nun packt man noch ne Funktion hinzu die ein Input String entsprechend splittet (z.b "1+1") und die dann entsprechend eine der 4 Funktionen aufruft.. voila, ein simpler Taschenrechner. Jenachdem wie viel Zeit man aufwendet & wieviele "Hacks" und Kniffe man nutzt, bekommt man das noch viel viel viel kürzer.
Es ab mal eine Webseite wo es als Challenge war Javascript Dinge in 140 bytes zu quetschen.. da haben leute total krasse Sachen reingequetscht bekommen von Tetris Spielen mit Grafiken bishin zu sonstigen Dingen.. da warn Tasschenrechner das kleinere Übel von der größe her :D

Das lässt sich sicher denke ich auch in C++ / C gut umsetzen wenn man die ganzen unnötigen abhängigkeiten dann weglässt und nicht unnötige libs verwendet.
Ansonsten halt echt vllt in Assembler.. :D

grüße

gORDon_vdLg
04.02.2018, 10:19
Schreibs in Assembler ;-P

Hätte ich auch gesagt wenn er nicht im C/C++ bereich gepostet hätte^^ Mit FASM z.B. kannste den output mode auf binary stellen und deine Exe direkt ganz selbst schreiben, dann wirds klein.

pav0c
04.02.2018, 13:37
Ja sorry hätte echt dazuschreiben sollen, dass es in C/C++ gemacht werden soll :D

Cystasy
04.02.2018, 13:42
Ja sorry hätte echt dazuschreiben sollen, dass es in C/C++ gemacht werden soll :D

Hast es ja in der richtigen Kategorie gepostet, sollte daher schon klar sein das es in C/C++ sein soll :redface:

sontyp
04.02.2018, 14:45
Ich glaube das hier (https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld) dürfte in die richtige Richtung gehen.
Der Trick ist also im Grunde genau das zu tun, was hier schon mehrmals erwähnt wurde: Tatsächliche Abhängigkeiten prüfen, separieren, sich vom unnötigen Kram verabschieden.

Da es sich ja um einen einfachen Taschenrechner handelt, würde ich vom Bauchgefühl her von C++ abraten. Der strukturelle Aufbau der Sprache lässt mich da bereits daran zweifeln, dass wir es schaffen, klein zu bleiben.

//EDIT:
So hab mich mal schlau gemacht und noch ein wenig gesucht. Es gibt wohl ein tolles tool (https://github.com/upx/upx/releases/tag/v3.94), das in der Lage sein soll, deine .exe kräftig runter zu rechnen durch bereits genannte Mechanismen. Dazu hab ich mir ein passenden Makefile zugelegt, dass nach Standard compilierungs Vorgang das Tool drüber laufen lässt.

Mein Code:

#include <stdio.h>
//#include <stdlib.h>

int main(int argc, char *argv[]) {
switch (argv[1][1]) {

case '+': printf("%d\n", ((int)argv[1][0]-48) + ((int)argv[1][2]-48));break;

case '-': printf("%d\n", ((int)argv[1][0]-48) - ((int)argv[1][2]-48));break;

case '/': printf("%d\n", ((int)argv[1][0]-48) / ((int)argv[1][2]-48));break;

case '*': printf("%d\n", ((int)argv[1][0]-48) * ((int)argv[1][2]-48));break;

default: printf("Failure");break;

}

return 0;

}

Nach normaler Compilierung: ca. 128kb
Mittels UPX (oben genanntes Tool): ca. 64kb

Wir müssen natürlich beachten, dass es sich hierbei um einen Compiler Vorgang unter Windows handelt (weil zu faul Lappi auszupacken), ABER mir ist gerade etwas rätselhaft, was man da noch abspecken möchte.


//EDIT No2:
Hab's jetzt noch mal unter Linux mitm GCC kompiliert und dabei einige Compiler Schalter verwendet.
gcc -0s -ffunction-sections -fdata-sections -Wl,--gc-sections -fno-exceptions -free main.c
danach noch gestript:
strip -s -R .comment -R .gnu.version --strip-unneeded a.out

Ergebnis: 6KB

Man möge beachten, dass das Parsing in meinem Beispiel unter aller Sau ist. Bin mir nicht sicher, ob das ganze nicht größer wird, wenn ich noch ordentlich parse.

sontyp
20.04.2018, 13:33
Moin,

hat sich daran noch mal jemand versucht und ist weitergekommen?

Greetz,
sontyp