1. C++ / Говнокод #18981

    −2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    unsigned strlen(const char *str)
    {
    	const char *ptr;
    	for (ptr = str; *ptr; ++ptr);
    	return ptr - str;
    }
    
    char *strcpy(char *dst, const char *src)
    {
    	while((*dst++ = *src++) != 0);
    	return dst;
    }
    namespace std
    {
    	class string
    	{
    	public:
    		string(const char *str = 0) : size(str ? strlen(str) : 0)
    		{
    			this->str = new char[size + 1];
    			if(str) strcpy(this->str, str);
    			else this->str[0]=0;
    		}
    		string(const string &str) : size(str.size)
    		{
    			this->str = new char[size +1];
    			strcpy(this->str, str.str);
    		}
    		~string()
    		{
    			delete[] str;
    		}
    		const char* c_str() const
    		{
    			return str;
    		}
    	private:
    		char *str;
    		unsigned size;
    	};
    
    	class Cout
    	{
    	public:
    		Cout &operator<< (const char *str)
    		{
    			unsigned len = strlen(str);
    			asm volatile (
    			"movl $0x04, %%eax\n" 
    			"movl $0x01, %%ebx\n"
    			"int $0x80\n"
    			:
    			: "c"(str), "d"(len));
    			return *this;
    		}
    		Cout &operator<< (const string &str)
    		{
    			operator<< (str.c_str());
    			return *this;
    		}
    	} cout;
    }
    
    int main()
    {
    	std::string str = "Hello World!";
    	std::cout << str << "\n";
    	return 0;
    }

    Ещё 1 хелловорлд для линуха x86 на С++

    Запостил: Koncord, 07 Ноября 2015

    Комментарии (52) RSS

    • Читер! new/delete надо было тоже делать через сисколлы.
      Ответить
    • Автор -- Бог переносимого кода.
      А не люблю AT&Tшный синтаксис
      Ответить
      • Куда переносимого то? Оно только на x86 заведётся...
        Ответить
        • Привет кэп
          Ответить
        • irony во все поля.
          Но всё же "Царь переносимого кода" звучало бы посильнее. С учётом местной специфики
          Ответить
        • Ошибаешься, на x86-64 тоже заведётся, в ядре оставлена совместимость.
          Ответить
          • Т.е. int 80h проверяет, какая битность у сегмента, который его позвал?
            Ответить
            • int 80h - это устаревший способ вызова функций ядра в x86-64. В x86-64 это можно сделать без прерываний, с помощью команды syscall, что на порядок быстрее и экономнее, но не совместимо с x86.
              Ответить
              • > но не совместимо с x86
                Ну там sysenter был.
                Ответить
              • Ну вот мне что интересно - если на время забыть про sysenter/syscall, то int 80h, вроде как, работает и там и там. А коды сисколлов, емнип, разные (ну и аргументы само собой 64-битные у x86_64 и в других регистрах). Значит ядро отличает, когда запрос приходит из compatibility, а когда из long? Или я гоню?
                Ответить
                • Да, гоню. Нихера оно не отличает. int 80h всегда дёргает 32-битные сисколлы. 64-битные можно позвать только через syscall.
                  Ответить
    • мне показалось, или тут тупо "копипаст всего что не скрыто дефайнами"?
      Ответить
      • Например? Если хочешь, могу полностью убрать stdlibc, но будет много ассемблера, а не только 1 вставка.
        Ответить
        • А нахуй асм, чё, вызов АПИ не работает?
          Ответить
          • Ну апи в либе, а либу ему как раз таки хочется отпилить.

            На самом деле, в винде точно так же. Все эти kernel32.dll и.т.п. просто более высокоуровневые обёрточки над сисколлами, которые можно дёргать через int/sysenter/syscall.
            Ответить
            • Апи в дллке, в сишке кажется есть средства подключения к функциям дллок.
              Ответить
              • Апи чего? В ядро передать управление можно только прерыванием, sysenter'ом, syscall'ом и call gate'ом (но я не видел, чтобы оси call gate юзали). Всё остальное, что есть в dll'ках/so'шках - такие же бесправные юзермодные функции, как и у твоей проги. Никакой магии в них нет, ты всегда можешь написать их сам.

                А ОП как раз таки захотел написать прогу, которая не будет юзать все эти сахарные so'шки, а будет общаться только с ядром операционки.
                Ответить
                • Я думал, он не хочет подключать stdlibc. Мне так показалось, потому что он сам так написал.
                  Отсутствие одного заголовка не мешает самому подключиться к нужным сошкам.
                  Ответить
                  • А в линухе всё основное api как раз в libc. Все эти read'ы, exit'ы это тонюсенькие обёртки над ядерными вызовами.

                    > одного заголовка
                    Ну и саму либу он тоже не линкует к проге.
                    Ответить
          • Ну, кстати, ещё вариант есть. Найти linux-gate.so в памяти, и позвать у него функцию, делающую сисколл одним из вышеперечисленных методов. Хотя... она тоже под асм заточена.
            Ответить
        • > будет много ассемблера
          http://ideone.com/UNXSt1

          P.S. ideone не даёт опции задавать, поэтому main().
          Ответить
          • http://ideone.com/x2OO4j
            Ответить
            • Я боюсь гэцэцэшных подставляемых символов. Мне они кажутся неинтуитивными.
              Ответить
              • Да там ёбаный пиздец. Куча мусора типа двойных процентов и долларов. Да ещё и всё вверх ногами. Неприятный ассемблер, если честно.

                Но интеграция того стоит - гцц старается, чтобы значения в нужных регистрах вовремя оказались и т.п. И в дизасме вставка не выглядит инородным телом, как в той же вижуалке.
                Ответить
                • Я не понимаю, для чего там макросы, заменяющиеся на регистры (типа "a" вместо ax/eax/rax). Это было бы объяснимо, если бы оно обеспечивало кроссплатформенность. Но ведь в любом случае при переносе на другую платформу придётся полностью переписывать все ассемблерные инструкции. Разве что иногда удастся сэкономить на замене eax→rax при портировании с x86 на x86_64.
                  Ответить
                  • Хер знает. Этот AT&T синтаксис вообще с какой архитектуры притащили? Может быть там все регистры однобуквенные были, как на тех же 8080.

                    Кстати, там же не только конкретные регистры можно писать, но и полезные штуки типа "любой регистр", "память", "память или регистр" и т.п.
                    Ответить
                    • не путайте Inline assambler с GCC AS это 2 разные вещи с одинаковым синтаксисом и GCC позволяет интел синтаксис
                      http://pastebin.com/CZGq2pLw
                      Парсер BBCode лох
                      "игнорировать \n" читай как "игнорировать \0"
                      Ответить
                      • Ошибся, коммент правильный.
                        PS. код писал давно.
                        Ответить
                  • Видимо для того, чтобы не париться с разрядностью. Буква превращается в нужный регистр автоматически в зависимости от типа переменной, которую туда записывают.
                    Ответить
              • Что такое а, бэ цэ, дэ?
                Ответить
          • Это Си! И даже не попытка запилить stdlibc
            PS. Точка входа в Linux не main, а _start.
            Ответить
            • Ну _start по дефолту, а так - хоть чё можно задать. В общем-то в самом ELF она безымянная.

              Но я же написал, почему там main... ideone команду компилятора не даёт поправить.
              Ответить
          • http://www.tutorialspoint.com/compile_cpp_online.php
            Вот тут можно задать свои ключи.
            Ответить
    • Вот конечный вариант без читерства :)
      http://www.tutorialspoint.com/compile_cpp_online.php?PID=0Bw_CjBb95KQMUEJqcVRrQTlNd3M
      Ответить
      • А почему бы не сделать mov ebx, eax в start'е, чтобы код возврата main()'а попал в exit()?
        Ответить

    Добавить комментарий