Малий Ендіанське число до перетворення рядків


13

Вступ

Під час роботи з генератором BMP (bitmap) я стикаюся з проблемою перетворення числа в маленький шістнадцятковий рядок. Ось функція, яку я створюю в JavaScript, але цікаво, як маленький код може працювати аналогічно

let liEnd= num => num.toString(16).padStart(8,'0').match(/../g).reverse().join``;
console.log(liEnd(304767)) // 304767 dec = 0x4a67f hex

Виклик

Функція запису, яка буде приймати на вході 32-бітне цілочисельне число, і виробляє 8-розрядний шістнадцятковий рядок з невеликим порядком ендіан. Приклад алгоритму, який виконує роботу:

  • конвертувати numb в шістнадцяткову рядок, наприклад: 304767 -> '4a67f'
  • додайте нульові накладки, щоб отримати 8-знакову рядок: '0004a67f'
  • розділити струну на чотири 2-х знакових частини: '00','04','a6','7f'
  • зворотний порядок штук '7f','a6','04','00'
  • з'єднайте шматки та поверніть як результат: '7fa60400'

Приклад введення та виводу

Номер вводу (або рядок з номером відхилення) знаходиться зліва від ->виводу, шестигранний рядок - справа

2141586432 -> 0004a67f
304767     -> 7fa60400

Відповіді:



6

Python 3 , 37 байт

lambda n:n.to_bytes(4,"little").hex()

Спробуйте в Інтернеті!

Рекурсивне рішення на основі арифметики ( 50 49 байт, працює також для Python 2 ) :

f=lambda n,i=4:i*'1'and"%02x"%(n%256)+f(n>>8,i-1)

Спробуйте в Інтернеті!

-1 байт завдяки @JonathanAllan


Я б сказав, подайте рекурсивний текст як запис Python 2 :)
Джонатан Аллан

f=lambda n,i=4:i*'1'and'%02x'%(n%256)+f(n>>8,i-1)рятує байт :)
Джонатан Аллан

@JonathanAllan Дякую Я не знайомий з усіма хитрощами Python 2 і не бачу, як їх можна скоротити.
Джоель

це не так, але 37 не працюватимуть в py 2
Джонатан Аллан

Так. Деякі з цих вбудованих програм є лише Python-3.
Джоель

6

R , 54 53 байти

format.hexmode(scan()%/%256^(0:3)%%256%*%256^(3:0),8)

Спробуйте в Інтернеті!

Кожна група з 2 символів насправді є шістнадцятковим поданням цифри в базі 256. scan()%/%256^(0:3)%%256Перетворює на базове 256 число з 4 цифрами, оберненими, ...%*%256^(3:0)приєднує їх до єдиного цілого числа та format.hexmode(...,8)перетворює це число у його шістнадцяткове представлення з 8 цифр.


5

JavaScript (ES7),  59  57 байт

Строкова маніпуляція.

n=>(n+2**32).toString(16).match(/\B../g).reverse().join``

Спробуйте в Інтернеті!

Як?

Спочатку перетворюємо н+232 в шістнадцятковий, щоб переконатися, що всі провідні 0 включаються:

(304767 + 2**32).toString(16) // --> '10004a67f'

Спробуйте в Інтернеті!

Ми використовуємо регулярний вираз, /\B../gщоб відповідати всім групам з 2 цифр, ігноруючи провідний 1 завдяки \B(безсловна межа ).

'10004a67f'.match(/\B../g) // --> [ '00', '04', 'a6', '7f' ]

Спробуйте в Інтернеті!

Ми reverse()і join()дістаємо остаточний рядок.


JavaScript (ES6), 61 байт

Рекурсивна функція.

f=(n,k=4)=>k?[(x=n&255)>>4&&'']+x.toString(16)+f(n>>8,k-1):''

Спробуйте в Інтернеті!


⭐ - ви отримуєте зірку за гарну відповідь - мені це подобається, короткий, але все-таки чистий і "людський для редагування" :)
Каміль Кийчевський


5

C # (Visual C # Interactive Compiler) , 54 байти

x=>$"{(x=x>>16|x<<16)>>8&16711935|(x&16711935)<<8:x8}"

Збережено 4 байти завдяки @PeterCordes

Спробуйте в Інтернеті!

Пояснення

x=>                                                    //Lambda taking in an uint
     (x=x>>16|x<<16)                                   //Swap the first two and the last two bytes of the uint (0x7fa60400 -> 0x04007fa6)
                    >>8&16711935|(x&16711935)<<8       //Swap each pair of bytes in every group of 2 bytes (0x04007fa6 -> 0x0004a67f)
  $"{                                           :x8}"  //Format as hex string, padded with leading zeroes to length 8

Чи можете ви зменшити 4278255360маску постійною до 16711935( 0xff00ff), якщо ви змістите перед маскуванням? Або це коштує додаткових парен? Крім того, якщо ні, то 0xff00ff00однакової довжини, але набагато більш значущо для людини.
Пітер Кордес

@PeterCordes Він також має додаткову перевагу в тому, що зможе видалити дужки, оскільки >>має вищий пріоритет, ніж коли &збережено 4 байти. Дякую!
Втілення невігластва

Класно. У вашому розділі "пояснення" я б запропонував написати константи в шістнадцятковій формі.
Пітер Кордес

4

Japt -P , 10 байт

sG ùT8 ò w

Спробуй це

sG ùT8 ò w     :Implicit input of integer
s              :Convert to string
 G             :  In base-16
   ù           :Left pad
    T          :  With 0
     8         :  To length 8
       ò       :Split into 2s
         w     :Reverse
               :Implicitly join and output

Що робить -P?
СС Енн

🚀 ваша відповідь у верхній частині (чи можете ви додати пояснення?)
Kamil Kiełczewski

@ JL2210 Від документа : " -P: Якщо вихід є масивом, виводиться без роздільника (тобто об'єднаний з P). " Отже прапор призначений для неявного замість явного приєднання для збереження байтів. :)
Кевін Круїссен

2
@ KamilKiełczewski, пояснення додано.
Shaggy


4

Python 2 , 43 байти

lambda n:[("%08x"%n)[i^6]for i in range(8)]

Спробуйте в Інтернеті!

-4 байти завдяки benrg

Виводить список символів. Обчислюється шляхом отримання, по порядку, шістнадцяткових цифр вхідних даних за індексами 6, 7, 4, 5, 2, 3, 0, 1.


2
[i^6]for i in range(8)економить кілька байт.
benrg

Чи дозволено виводити список замість рядка?
Qwertiy

вихід як список не дуже підходить для духу питання imo
qwr

3

C (gcc) ендіатичний агностик, без стандартних ліб, 92 91 байт

h(n)- це однозначна цілочисельна-> шестигранна функція помічника.
f(x,p)приймає ціле число і char[8]покажчик. Результат - 8 байт charданих. ( Не припиняється на 0, якщо тільки абонент не робить цього.)

Припущення: набір символів ASCII. Доповнення 2, intтак що правильний зсув врешті-решт знижує біт знака, а перетворення на uint32_tв intне з’єднує біт-шаблон, якщо встановлено високий біт. intпринаймні 32-розрядна. (Ширше може дозволити йому працювати над реалізацією доповнення 1 або значущою величиною C).

Неприпущення: що-небудь щодо порядку виконання байтів або підписання char.

i;h(n){n&=15;return n>9?n+87:n+48;}f(x,p)char*p;{for(i=5;--i;x>>=8)*p++=h(x>>4),*p++=h(x);}

Спробуйте в Інтернеті! включаючи тестовий абонент, що використовує printf("%.8s\n", buf)для друку вихідного буфера без 0-кінця.

Безголівки:

int h(n){n&=15;return n>9 ? n+'a'-10 : n+'0';}      // single digit integer -> hex

int i;
void ungolfed_f(x,p)char*p;{
    for(i=5; --i; x>>=8)   // LS byte first across bytes
        *p++=h(x>>4),      // MS nibble first within bytes
        *p++=h(x);
}

Робота n&=15;всередині h(x)є беззбитковою; Там 6 байтів проти 3 для кожного, &15щоб виділити низьку риску в обох сайтах виклику.

,- це точка послідовності (або еквівалент у сучасній термінології), тому безпечно робити *p++= stuffдвічі в одному операторі, коли їх розділяє ,оператор.

>>на підписане ціле число визначається як арифметичне, так і логічне. GNU C визначає це як доповнення арифметики 2. Але на будь-якій машині доповнення будь-якого 2 це насправді не має значення, оскільки ми ніколи не дивимося на змінені 0 або копії біта знака. Оригінальний MSB з часом потрапить у низький байт без змін. Це не за ознакою / величиною, і я не впевнений у додатку 1.

Таким чином, це може бути переносним лише для 2-х реалізацій доповнення C. (Або де intце ширше , ніж 32 біта , тому біт 31 тільки частина величини.) Без знака -> підписали перетворення також munges біт-шаблон для негативних цілих чисел, так що &15на intб витягти тільки гризе вихідного беззнаковое значення на 2 з доповненням. Знову ж таки, якщо intвона не була ширшою за 32-бітну, тому всі входи невід'ємні.

Версія для гольфу має UB від падіння до кінця недійсної функції. Не повертати значення, просто щоб не оголосити його voidзамість за замовчуванням int. Сучасні компілятори вирішать це за умови активізації.


Мотивація: Я розглядав відповідь Asm на палець x86 або ARM, думав, що це може бути цікаво зробити це вручну на C, можливо, для відпрацьованого компілятором ASM як вихідної точки. Дивіться /programming/53823756/how-to-convert-a-number-to-hex щодо швидкодіючої швидкості x86, включаючи версію AVX512VBMI, яка містить лише 2 інструкції (але потрібні вектори управління для vpmultishiftqb та vpshufb так що не було б чудово для гольфу). Зазвичай для SIMD потрібна додаткова робота, щоб перевернути байт в порядок друку на маленькій ендіанській x86, тому цей байт-зворотний шестигранний вихід насправді простіший, ніж зазвичай.


Інші ідеї

Я розглядав можливість приймати ціле число за допомогою посилання та перебирати його байти char*за допомогою малоінтенсивного виконання C (наприклад, x86 або ARM). Але я не думаю, що це б значно заощадило.

Використовуючи sprintfробити 1 байт одночасно, 64 байти після гри в гольф:

int i;
void f(x,p)char*p;{
        for(i=4;sprintf(p,"%.2x",x&255),--i;x>>=8)
                p+=2;
}

Але якщо ми використовуємо функції, схожі на printf, ми можемо також замінити байт і зробити %xprintf всього цього, як відповідь @ JL2210 .


⭐ - ви отримуєте зірку за приємну відповідь
Каміль Кийчевський

3

x86 SIMD-код машини (AVX512-VBMI), 36 байт

(16 байт - шістнадцяткова таблиця пошуку)

Це функція, яка бере ціле число xmm0і повертає 8 байт даних даних ASCII xmm0, щоб абонент міг зберігати, де захоче. .

З C, називайте це як __m128i retval = lehex(_mm_cvtsi32_si128(x))у конвенції про виклики x86-64 System V або MS Windows vectorcall.

# disassembly with machine-code bytes (the answer) and NASM source code.
0000000000401000 <lehex>:
  401000:       c5 f1 72 d0 04          vpsrld      xmm1, xmm0, 4         ; AVX1
  401005:       c5 f1 60 c8             vpunpcklbw  xmm1, xmm1, xmm0      ; AVX1
  401009:    62 f2 75 08 8d 05 01 00 00 00 vpermb  xmm0, xmm1, [rel .hex_lut]
  401013:       c3                      ret    

0000000000401014 <lehex.hex_lut>:
  401014:     30 31 ...  61 62 ...     .hex_lut:  db "0123456789abcdef"

Всього = 0x24 = 36 байт.

Див. Як перетворити число в шістнадцятковий? на SO для того, як це працює. (SSE2 для shift / punckck, тоді vpermbзберігається робота, яка нам знадобиться pshufb. AVX1 замість SSE2 / SSSE3 також уникає movapsреєстраційної копії.)

Зверніть увагу, що punpcklbwз операндами-джерелами в такому порядку дадуть нам найзначнішу байку з низьким вхідним байтом в найнижчому байтовому елементі, а потім найменш значущу прискіпливість найнижчого байта джерела. (У такому відповіді "SO" bswapна вході використовується a, щоб отримати результат у стандартному порядку друку лише з SSE2. Але тут ми хочемо цього порядку: високий nibble в нижньому елементі в кожному байті, але все ще мало-endian байд порядку).

Якби у нас було більше констант даних, ми могли би зберегти простір в режимі адресації, виконавши один із них, mov edx, imm32використовуючи [rdx+16]або будь-які режими адресації. Або vpbroadcastb xmm0, [rdx+1].

Але я думаю, що 16-байтовий шістнадцятковий LUT + vpermbвсе ще краще, ніж реалізація n>9 : n+'a'-10 : n+'0'умови: для цього потрібні 3 константи і принаймні 3 інструкції з байтовим маскуванням AVX512BW (порівняйте в масці vpaddb, об'єднаному маскуванні vpaddb) або більше з AVX1 або SSE2. (Див. Як перетворити число в шістнадцятковий? На SO для SSE2 версії цього). І кожна інструкція AVX512BW має принаймні 6 байт (4-байтний EVEX + опкод + modrm), довший зі зміщенням в режимі адресації.

Насправді знадобиться щонайменше 4 інструкції, оскільки нам потрібно очистити високий сміття за допомогою andps(або EVEX vpanddз 4-байтовим операндом пам'яті широкомовної передачі) перед порівнянням. І кожному з них потрібна інша константа вектора. AVX512 має операнди оперативної пам’яті, але лише для 32-бітних елементів і більше. напр ., останній операнд EVEXvpaddb є лише xmm3/m128, ні xmm3/m128/m8bcst. (Порти завантаження Intel можуть робити лише 32 та 64-розрядні трансляції безкоштовно як частину завантаження, тому Intel розробила AVX512BW так, щоб відображати це і взагалі не мати можливості кодувати операнди пам'яті байтового чи слово мовлення, замість того, щоб дати їм можливість робіть трансляції dword, щоб ви все ще могли стискати константи до 4-х байт: /.)

Причина, що я використовував AVX512VBMIvpermb замість SSSE3 / AVX1, pshufbє двоякою:

  • vpermbігнорує високі біти селекторів. (v)pshufbнульові байти відповідно до великого біта контрольного вектора і потребували б додаткової pandабо andpsфактичної ізоляції нив. З розміром XMM / 16-байт vpermbрозглядає лише низькі 4 біти елементів керування переміщенням, тобто біти [3:0]в позначеннях Intel в розділі " Операція" .
  • vpermbможе приймати дані для перемішування (таблицю пошуку) як операнд пам'яті. (v)pshufbОперанд xmm / mem є вектором керування переміщенням.

Зауважте, що AVX512VBMI доступний лише на CannonLake / Ice Lake, тому для перевірки цього вам, мабуть, потрібен тренажер, як SDE від Intel.


⭐ - ви отримуєте зірку за гарну відповідь
Kamil Kiełczewski

@ KamilKiełczewski: lol дякую. Ефективне перетворення чисел у шістнадцятку - одна з моїх улюблених речей. Це приємний випадок для використання декількох акуратних трюків та маніпуляцій бітом.
Пітер Кордес

3

Scala , 58 40 36 байт

"%08X"format Integer.reverseBytes(_)

Спробуйте в Інтернеті!

Досі використовує вбудований модуль для зворотного перетворення байтів Int, але використовує formatдля форматування формату IntHex. Не потрібно телефонувати toHexString.

Парені видалено format. Це означає, що аргумент можна брати неявно, використовуючи _.


2

Четвертий (gforth) , 52 51 40 байт

: f hex 0 4. do <# # # 0. #> type loop ;

Спробуйте в Інтернеті!

Пояснення коду

: f           \ start a new word definition
  hex         \ set the current base to base 16
  0           \ convert the input number to a double-cell integer
  4. do       \ start a counted loop from 0 to 3
    <# # #    \ start a formatted numeric string and move last 2 digits to format area
    0.        \ move remaining digits down the stack
    #>        \ delete top two stack value and convert format area to string
    type      \ output string
  loop        \ end loop
;             \ end word definition



2

Excel, 91 байт

=RIGHT(DEC2HEX(A1,8),2)&MID(DEC2HEX(A1,8),5,2)&MID(DEC2HEX(A1,8),3,2)&LEFT(DEC2HEX(A1,8),2)

2

К4 , 12 11 байт

Рішення:

,/$|4_0x0\:

Приклади:

q)k),/$|4_0x0\:304767
"7fa60400"
q)0W
"0004a67f"

Пояснення:

Насправді саме те, що задає питання:

,/$|4_0x0\: / the solution
      0x0\: / split to bytes
    4_      / drop first 4 bytes
   |        / reverse
  $         / convert to string
,/          / flatten

Примітки:

  • -1 байт, оскільки номери K4 за замовчуванням є довгими (64 біт), тому випадаючи 4 байти (32 біт)

🚀 Ваша відповідь вгорі
Каміль Кишевський

2

PHP , 31 байт

<?=unpack(H8,pack(V,$argn))[1];

Спробуйте в Інтернеті!

Скориставшись пакетом PHP та розпакуванням , я запаковую непідписаний вхід у форматі "32-бітовий маленький ендіайтовий порядок байтів" ( V) у двійкову рядок, а потім розпаковую його у форматі "шістнадцятковий рядок, перший з ключем" (H ) та надрукував результат.

Здається, це один з рідкісних випадків, коли вбудовані PHP насправді коротші, ніж реалізація простого алгоритму!


PHP pack()/ unpack()функції є приголомшливими для 0 разів, коли вони вам знадобляться у більшості PHP-проектів. З повагою, ви знайшли їхнє використання!
640 Кб

1

Вугілля деревне , 11 байт

⪫⮌⪪﹪%08xN²ω

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

        N   Input as a number
   ﹪%08x    Format using literal string
  ⪪      ²  Split into pairs of characters
 ⮌          Reverse
⪫         ω Join
            Implicitly print

19 байт, не вдаючись до форматування Python:

⪫…⮌⪪⍘⁺X²¦³⁶N¹⁶¦²¦⁴ω

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

           N        Input as a number
     ⁺              Plus
       ²            Literal 2
      X             To power
         ³⁶         Literal 36
    ⍘               Convert to base
            ¹⁶      Literal 16
   ⪪           ²    Split into pairs of digits
  ⮌                 Reverse the list
 …               ⁴  Take the first 4 pairs
⪫                 ω Join together
                    Implicitly print

🚀 ваша відповідь у верхній частині
Kamil Kiełczewski


1

J , 10 байт

8{._1{3!:3

Спробуйте в Інтернеті!

як

3!:3є J «іноземний союзом» для шестнадцатиричного уявлення, документований тут . Тобто це вбудований для перетворення в шістнадцять. Однак виводити це не зовсім те, що ми хочемо. Наприклад, працює:

3!:3 (304767)

виробляє:

e300000000000000
0400000000000000
0100000000000000
0000000000000000
7fa6040000000000

Значення інших рядків пояснюється на сторінці документа, яку я пов’язував вище. У будь-якому випадку зрозуміло, що ми хочемо перших 8 символів останнього рядка.

_1{ отримати останній рядок.

8{. отримує перші 8 символів.


🚀 Ваша відповідь вгорі
Каміль Кишевський

1

Рубі , 31 27 байт

Нарешті, це порт відповіді PHP Night2, тому що Ruby має той же функціональний пакет / розпакування.

->*i{i.pack(?V).unpack'H8'}

Спробуйте в Інтернеті!

Моя оригінальна відповідь на 31 байт, яка не скористалася режимом розпакування H8, тому що я не знав про це:

->*i{'%02x'*4%i.pack(?V).bytes}

Спробуйте в Інтернеті!


1

Пакет Windows, 90 байт

@for /l %%x in (24,-8,0)do @set/aa=%1^>^>%%x^&255&cmd/cexit !a!&<nul set/p=!=exitcode:~-2!

Запустіть командний рядок з / v, щоб увімкнути затримку розширення.


1

32-бітний машинний код x86, 24 21 байт

changelog: -3 байти: замініть стандартний add / cmp / jbe / add на злом DAS від @peter ferrie

64-розрядні: ще 24 байти. Тривалий режим видалив код DAS.
16-бітний режим: розмір операнду за замовчуванням - 16-розрядний, але специфікація проблеми по суті є 32-розрядною. У тому числі 8 шістнадцяткових цифр із твердим кодом.


Зворотний байт, а bswapпотім ручний int-> шестигранник у стандартному порядку (найзначніше спочатку, записування шістнадцяткових цифр у буфер виводу char у порядку зростання). Це дозволяє уникнути необхідності розкручувати цикл для переключення порядку між nibbles у байті vs. через байти.

Викликається void lehex(char buf[8] /*edi*/, uint32_t x /*esi*/);як x86-64 System V, за винятком того, що це не працює в 64-бітному режимі. (Для цього потрібен вихідний вказівник в EDI для stosb. Номер введення може бути в будь-якому регістрі, крім ECX або EAX.)

     1                             lehex:
     2 00000000 0FCE                   bswap  esi
     3 00000002 6A08                   push   8            ; 8 hex digits
     4 00000004 59                     pop    ecx
     5                             .loop:                ;do{
     6 00000005 C1C604                 rol    esi, 4       ; rotate high nibble to the bottom
     7                             
     8 00000008 89F0                   mov    eax, esi
     9 0000000A 240F                   and    al, 0x0f     ; isolate low nibble
    10 0000000C 3C0A                   cmp al, 10          ; set CF according to digit <= 9
    11 0000000E 1C69                   sbb al, 0x69        ; read CF, set CF and conditionally set AF
    12 00000010 2F                     das                 ; magic, which happens to work
    13                             
    14 00000011 AA                     stosb               ; *edi++ = al
    15 00000012 E2F1                   loop  .loop       ; }while(--ecx)
    16                             
    17 00000014 C3                     ret

розмір = 0x15 = 21 байт.

32-бітний тестовий випадок TIO FASM x86 з writeвикликом ASM, який використовує системний виклик для запису виводу після виклику його двічі для додавання 2 рядків у буфер. Перевіряє всі шістнадцяткові цифри 0..F, включаючи 9 і A на межі між цифрою та літерою.

DASХак - x86 має прапор половинній перенесення, для перенесення з - за низької клювання. Корисно для упакованих BCD-матеріалів, таких як інструкція DAS, призначених для використання після віднімання двох двозначних чисел BCD. Оскільки низький ступінь AL перебуває за межами діапазону 0-9, ми напевно зловживаємо цим.

Зверніть увагу на if (old_AL > 99H) or (old_CF = 1)ТОТУ AL ← AL − 60H;частину розділу "Експлуатація" в керівництві; sbb завжди встановлює тут CF, так що частина завжди буває. Саме та діапазон ASCII для великих літер - це те, що мотивує вибірsub al, 0x69

  • cmp 0xD, 0xA не встановлює CF
  • sbb 0xD - 0x69завершує AL = 0xA4як вхід до DAS. (І встановлює CF, очищає AF)
  • немає AL - = 6 у першій частині DAS (тому що 4> 9 неправдиво, а AF = 0)
  • AL - = 0x60 у другій частині, залишаючи 0x44код ASCII для'D'

проти цифри:

  • cmp 0x3, 0xA встановлює CF
  • sbb 3 - 0x69 - 1= AL = 0x99 і встановлює CF та AF
  • немає AL - = 6 у першій частині DAS (9> 9 помилково, але встановлено AF), залишаючи 0x93
  • AL - = 0x60 у другій частині, залишаючи 0x33, код ASCII для '3'.

Віднімання 0x6aв SBB встановить AF для кожної цифри <= 9, тому всі цифри слідують одній логіці. І залиште його очищеним для кожної букви з алфавіту. тобто правильно використовувати розділене керування DAS 9 / A.


Зазвичай (для продуктивності) ви використовуєте таблицю пошуку для скалярного циклу або, можливо, 2х безрозгалуженого leaі cmp/cmovумовне додавання. Але 2-байтні al, imm8інструкції - це велика вигода для розміру коду.


x86-64 версія для : тільки та частина , яка відрізняється, між and al, 0xfі stosb.

;; x86-64 int -> hex  in 8 bytes
    10 0000000C 0430                   add    al, '0'
    11 0000000E 3C39                   cmp    al, '9'
    12 00000010 7602                   jbe  .digit
    13 00000012 0427                     add    al, 'a'-10 - '0'     ; al =  al>9 ? al+'a'-10 : al+'0'
    14                             .digit:

Зауважте, що add al, '0' завжди працює, а умовне додавання лише додає різницю між 'a'-10і '0', щоб зробити це просто ifзамість if/else .

Тестується та працює, використовуючи той самий mainдзвонильник, що і мій відповідь C , який використовує char buf[8]та printf("%.8s\n", buf).


Ви можете створити онлайн-фрагмент, наприклад, тут ?
Kamil Kiełczewski

@ KamilKiełczewski: TIO унеможливлює (AFAIK) записувати абонента на C, щоб перевірити функцію asm, тому я часто не турбуюсь, але впевнений, оскільки ви просили і sys_writeможете легко виводити рядки фіксованої довжини. Що цікаво, я не зрозумів, що FASM на TIO дозволяє вам створювати 32-бітні виконувані файли, на відміну від NASM, де він не поважає -felf32. Я все одно віддаю перевагу x86-64, і ця відповідь не зберігає жодного байту від 32-бітного коду.
Пітер Кордес

⭐ - ви отримуєте зірку за приємну відповідь
Каміль Кийчевський

1
@ JL2210: Ви маєте на увазі sprintf? Я не думаю, що libc не має будь-яких зручних функцій int-> string, крім функцій на основі формату-рядка, лише string-> int, як strtoul. Але так, bswap / printf, ймовірно, буде коротшим, якщо ви можете придумати якийсь спосіб підрахунку байтів для запису GOT для функції в динамічній бібліотеці (окрім 6-байтового call [rel printf wrt ..got]сайту виклику); мінімальний статично пов'язаний виконуваний файл може бути значно меншим, ніж динамічний, принаймні, коли це робиться за ldдопомогою звичайних стандартних значень. Але я не думаю, що було б доцільно статично пов’язувати його, але не рахувати його розмір коду.
Пітер Кордес

1
@ JL2210: Пам'ятайте, що це відповідь машинного коду x86 , а не розмір джерела тексту ASM. Я не використовував функції libc у попередніх відповідях на машинний код, лише системні дзвінки в Linux (наприклад, у Фібоначчі) та IDK, як би я подумав про підрахунок вартості чи хочу я навіть написати відповіді машинного коду з libc. . Існують випадки використання для машинного коду x86, коли libc недоступний, наприклад, у завантажувачі.
Пітер Кордес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.