- 1
Почему при таком обилии языков программирования ассемблер не уходит в туман?
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1
Почему при таком обилии языков программирования ассемблер не уходит в туман?
К нему возвращаются опять и опять, и, что удивительно, тем чаще, чем язык высокоуровневей.
Напоминает попытки быдла бросить курить.
0
// https://godbolt.org/z/f4s13WEWM
#include <inttypes.h>
int test(uint32_t a, uint32_t b)
{
if (a > b)
return a+b;
return a*b;
}
int test2(uint32_t a, uint32_t b)
{
return (a+b)*(a > b) | (a*b)*!(a > b);
}
int test3(uint32_t a, uint32_t b)
{
return
((a+b) & (uint32_t)(!(a > b) - 1)) |
((a*b) & (uint32_t)((a > b) - 1));
}
int test4(uint32_t a, uint32_t b)
{
const uint32_t arr[2] = {a+b, a*b};
return arr[!(a > b)];
}
/* ASM output
test:
bltu a1, a0, .LBB0_2
mul a0, a1, a0
ret
.LBB0_2:
add a0, a0, a1
ret
test2:
bltu a1, a0, .LBB1_2
mul a0, a1, a0
ret
.LBB1_2:
add a0, a0, a1
ret
test3:
bltu a1, a0, .LBB2_2
mul a0, a1, a0
ret
.LBB2_2:
add a0, a0, a1
ret
test4:
addi sp, sp, -16
add a2, a1, a0
mul a3, a1, a0
sltu a0, a1, a0
sw a2, 8(sp)
sw a3, 12(sp)
xori a0, a0, 1
slli a0, a0, 2
addi a1, sp, 8
add a0, a0, a1
lw a0, 0(a0)
addi sp, sp, 16
ret
*/
Наглядная демонстрация того, что компилятор может насрать на ваши попытки заставить его сгенерить branchless машинный код. Получилось это только в "test4"
0
extern char* strcat( char* dest, const char* src );
extern int printf ( const char * restrict format, ... );
extern int putchar( int ch );
#define LISPER(n, l, re) ({ \
auto int ii = l; \
static unsigned char n[l]; \
while (ii--) { \
*str##n(n, (unsigned char[]){0x09 >> 1 << 1, 0x1911 >> 0xD}); \
}; \
*((void**)&re) = printf((unsigned char[]){0x25, 0x73, 0x1917 >> 0xE}, n); \
})
struct bombitterLemon{
union {
unsigned char : 0;
unsigned char : 0;
unsigned char v: 7;
} pacific;
};
int main(void) {
struct bombitterLemon b0;
LISPER(cat, 0x40 ^ (2 << 2), b0);
(*putchar) (*(struct wtf**)&b0);
LISPER(cat, ((int) (((char*) (0x8 ^ (1 << 6))) - 3) | 1), b0);
(**putchar) (*(struct is***)&b0);
LISPER(cat, ((int) (((short*) (0x9 << 3))) | 4), b0);
(***putchar) (*(struct that****)&b0);
LISPER(cat, ((int) (((int*) (0x12 << 2))) | 4), b0);
(**putchar) (*(unsigned char*****)&b0);
LISPER(cat, ((int) (((long*) (0x90 >> 1))) | 4 | 2 | 1), b0);
(*putchar) (b0.pacific.v);
}
Классический собесный говнокод для кунов на громкие позиции malware ANALyst, security дрист-searcher и даже (о, ужас) compiler devteam в известные шарашки.
Шланг<15 и ICC жуют с говном не глядя. Чего не сказать о бычаре, дристающего на коврик.
Осилил, анонимус? Поясни пацанам на пальцах за высер без единого include с ноября прошлого.
0
void main() {
ph_fork f1, f2, f3, f4, f5;
f_arr[0] = &f1;
f_arr[1] = &f2;
f_arr[2] = &f3;
f_arr[3] = &f4;
f_arr[4] = &f5;
philosopher ph1, ph2, ph3, ph4, ph5;
ph_arr[0] = &ph1;
ph_arr[1] = &ph2;
ph_arr[2] = &ph3;
ph_arr[3] = &ph4;
ph_arr[4] = &ph5;
f1.number = 1;
sem_init(&f1.is_free, 0, 1);
f2.number = 2;
sem_init(&f2.is_free, 0, 1);
f3.number = 3;
sem_init(&f3.is_free, 0, 1);
f4.number = 4;
sem_init(&f4.is_free, 0, 1);
f5.number = 5;
sem_init(&f5.is_free, 0, 1);
ph1.number = 1;
ph1.ph_fork_amount = 0;
ph1.ph_forks[0] = 1;
ph1.ph_forks[1] = 2;
ph1.times_eaten = 0;
ph1.times_thought = 0;
ph1.st = THINKING;
pthread_create(&ph1.thread, NULL, routine, (void*)&ph1);
ph2.number = 2;
ph2.ph_fork_amount = 0;
ph2.ph_forks[0] = 2;
ph2.ph_forks[1] = 3;
ph2.times_eaten = 0;
ph2.times_thought = 0;
ph2.st = THINKING;
pthread_create(&ph2.thread, NULL, routine, (void*)&ph2);
ph3.number = 3;
ph3.ph_fork_amount = 0;
ph3.ph_forks[0] = 3;
ph3.ph_forks[1] = 4;
ph3.times_eaten = 0;
ph3.times_thought = 0;
ph3.st = THINKING;
pthread_create(&ph3.thread, NULL, routine, (void*)&ph3);
ph4.number = 4;
ph4.ph_fork_amount = 0;
ph4.ph_forks[0] = 4;
ph4.ph_forks[1] = 5;
ph4.times_eaten = 0;
ph4.times_thought = 0;
ph4.st = THINKING;
pthread_create(&ph4.thread, NULL, routine, (void*)&ph4);
ph5.number = 5;
ph5.ph_fork_amount = 0;
ph5.ph_forks[0] = 5;
ph5.ph_forks[1] = 1;
ph5.times_eaten = 0;
ph5.times_thought = 0;
ph5.st = THINKING;
pthread_create(&ph5.thread, NULL, routine, (void*)&ph5);
pthread_join(ph1.thread, NULL);
pthread_join(ph2.thread, NULL);
pthread_join(ph3.thread, NULL);
pthread_join(ph4.thread, NULL);
pthread_join(ph5.thread, NULL);
sem_destroy(&f1.is_free);
sem_destroy(&f2.is_free);
sem_destroy(&f3.is_free);
sem_destroy(&f4.is_free);
sem_destroy(&f5.is_free);
printf("\nThe lunch has ended!\n--------\nRESULTS:\nPhilosopher 1 has eaten %d times and thought %d times\nPhilosopher 2 has eaten %d times and thought %d times\nPhilosopher 3 has eaten %d times and thought %d times\nPhilosopher 4 has eaten %d times and thought %d times\nPhilosopher 5 has eaten %d times and thought %d times\n", ph1.times_eaten, ph1.times_thought, ph2.times_eaten, ph2.times_thought, ph3.times_eaten, ph3.times_thought, ph4.times_eaten, ph4.times_thought, ph5.times_eaten, ph5.times_thought);
}
Решение задачи про обедающих философов, часть вторая.
0
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
typedef struct _ph_fork {
int number;
sem_t is_free;
} ph_fork;
typedef enum state {
EATING,
THINKING
} state;
typedef struct _philosopher {
int number;
int ph_fork_amount;
int ph_forks[2];
int times_eaten;
int times_thought;
state st;
pthread_t thread;
} philosopher;
ph_fork* f_arr[5] = {0};
philosopher* ph_arr[5] = {0};
void* routine(void* arg) {
philosopher* ph = (philosopher*)arg;
int frks[2] = {0};
frks[0] = ph->ph_forks[0];
frks[1] = ph->ph_forks[1];
int ph_fork_left_odd = frks[0] % 2;
int ph_fork_right_odd = frks[1] % 2;
printf("Philosopher %d has taken a seat at the table.\n", ph->number);
for (int i = 0; i < 72; i++) {
if (!(ph_fork_left_odd && ph_fork_right_odd)) {
if (ph_fork_left_odd) {
sem_wait(&f_arr[frks[0] - 1]->is_free);
printf("Philosopher %d takes left fork…\n", ph->number);
ph->ph_fork_amount++;
sem_wait(&f_arr[frks[1] - 1]->is_free);
printf("Philosopher %d takes right fork…\n", ph->number);
ph->ph_fork_amount++;
}
if (ph_fork_right_odd) {
sem_wait(&f_arr[frks[1] - 1]->is_free);
printf("Philosopher %d takes right fork…\n", ph->number);
ph->ph_fork_amount++;
sem_wait(&f_arr[frks[0] - 1]->is_free);
printf("Philosopher %d takes left fork…\n", ph->number);
ph->ph_fork_amount++;
}
} else { // Special case when both ph_forks are odd
sem_wait(&f_arr[frks[0] - 1]->is_free);
printf("Philosopher %d takes left fork…\n", ph->number);
ph->ph_fork_amount++;
sem_wait(&f_arr[frks[1] - 1]->is_free);
printf("Philosopher %d takes right fork…\n", ph->number);
ph->ph_fork_amount++;
}
if (ph->ph_fork_amount == 2) {
ph->st = EATING;
ph->times_eaten++;
printf("Philosopher %d is eating…\n", ph->number);
sleep(1);
};
if (!(ph_fork_left_odd && ph_fork_right_odd)) {
if (ph_fork_left_odd) {
printf("Philosopher %d puts back left fork…\n", ph->number);
sem_post(&f_arr[frks[0] - 1]->is_free);
ph->ph_fork_amount--;
printf("Philosopher %d puts back right fork…\n", ph->number);
sem_post(&f_arr[frks[1] - 1]->is_free);
ph->ph_fork_amount--;
}
if (ph_fork_right_odd) {
printf("Philosopher %d puts back right fork…\n", ph->number);
sem_post(&f_arr[frks[1] - 1]->is_free);
ph->ph_fork_amount--;
printf("Philosopher %d puts back left fork…\n", ph->number);
sem_post(&f_arr[frks[0] - 1]->is_free);
ph->ph_fork_amount--;
}
} else { // Special case when both ph_forks are odd
printf("Philosopher %d puts back left fork…\n", ph->number);
sem_post(&f_arr[frks[0] - 1]->is_free);
ph->ph_fork_amount--;
printf("Philosopher %d puts back right fork…\n", ph->number);
sem_post(&f_arr[frks[1] - 1]->is_free);
ph->ph_fork_amount--;
}
if (ph->ph_fork_amount == 0) {
ph->st = THINKING;
printf("Philosopher %d is thinking…\n", ph->number);
ph->times_thought++;
sleep(1);
}
}
printf("Philosopher %d has finished his lunch and left.\n", ph->number);
return NULL;
};
Решение задачи про обедающих философов, часть первая.
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
size_t buflen;
size_t i;
char *obuffer;
if (argc != 2) {
fprintf(stderr, "Usage: %s 'some ASCII string'\n", argv[0]);
fprintf(stderr, "\tconvert the string into overlong UTF-8.\n");
return 1;
}
buflen = strlen(argv[1])*2+1;
obuffer = malloc(buflen);
if (obuffer == NULL) {
fprintf(stderr, "Error: cannot allocate %zd bytes of memory.", buflen);
return 2;
}
for (i=0; argv[1][i]; i++) {
obuffer[2*i] = 0xC0|(argv[1][i]>>6);
obuffer[2*i+1] = 0x80|(argv[1][i]&0x3F);
}
obuffer[2*i] = '\0';
puts(obuffer);
free(obuffer);
return 0;
}
В UTF-8 запрещено использовать кодовые последовательности не минимальной длины, например юникоды с номером до 127 требуется кодировать именно в один байт, а не в 2,3 и так далее. А если так всё-таки сделать, полученная фигня называется оверлонгом (overlong). Вот этот код их как раз и создаёт. Но только из ASCII символов и расширяя их только до двух байт. Написание более универсального варианта, если вдруг кому-то надо оставляем как упражнение для читателя.
Что интересно, некоторые текстовые редакторы, если в них открыть файл, сделанный этой программой, увидят обычный текст.
0
// https://github.com/AlexCeleste/C99-Lambda
// # C99-Lambda: nested functions, lambdas, and closures, in ISO C99
// https://github.com/AlexCeleste/C99-Lambda/blob/57583080392d5f3f626034bbb3292eb0070ba304/c_lambda.h#L110
// Internal lambda builder functions
#define FN_8CL_ARG_TYPE(T) , T
#define FN_8FEXP(call, p, f, R) { FN_8GETTYPE_8fn f = fn f; call(M_ID p M_IF(M_2ORMORE R, (_fun, M_REST_ R), (_fun))); }
#define FN_8CLEXP(call, p, c, R) { void * _fun = cl c; call(M_ID p M_IF(M_2ORMORE R, (_fun, M_REST_ R), (_fun))); }
#define FN_8EMIT_NS(N, H, B, Q) FN_8EMIT_NS_((FN_8GET_NL(N, B)), H, (M_ZIP_W2(FN_8EMIT_ELEM, B, M_ILIST)), Q)
#define FN_8EMIT_NS_(NL, H, BL, Q) (8ZIPNE,(NL, BL, Q), FN_8EMIT_BODY(NL, H, BL))
#define FN_8GET_NL(N, B) M_ZIP_W2(FN_8GET_NL_1, M_ENLIST(_8anon_##N##_, M_NARGS B), M_ILIST)
#define FN_8GET_NL_1(A, B) , M_CONC_(A, B)
#define FN_8EMIT_BODY(NL, H, BL) M_ID H M_ZIP_WITH(FN_8EMIT_BLOCK, BL, NL)
#define FN_8EMIT_ELEM(E, _) ,M_CONC_(FN_8EMIT_, E)
#define FN_8EMIT_8blk(...) (1, 0, __VA_ARGS__)
#define FN_8EMIT_8fn(...) (0, 0, __VA_ARGS__)
#define FN_8EMIT_8cl(...) (0, 1, __VA_ARGS__)
#define FN_8EMIT_BLOCK(P, N) M_IF(M_FIRST P, (M_REST2 P), (FN_8EMIT_NAME((M_REST P, r, a, o), N)))
#define FN_8EMIT_NAME(P, N) M_IF(M_FIRST P, (FN_8EMIT_CL(N, M_ID P)), (N))
#define FN_8EMIT_CL(...) FN_8EMIT_CL_(__VA_ARGS__)
#define FN_8EMIT_CL_(n, _, r, a, o, ...) (void*)&(struct n##_env_t){ \
n,sizeof(struct n##_env_t) M_FOR_EACH(FN_8CL_SND, M_ID o) }
#define FN_8CL_SND(P) , M_REST_ P
#define FN_8EMIT_ENV(E, Q) (8DO_Q, (Q), FN_8EMIT_ENV_(E))
#define FN_8EMIT_ENV_(n, rt, a, o) struct n##_env_t { \
FN_8CTYPE(rt, n, a, _fun); size_t _size; M_FOR_EACH(FN_8FLDS, M_ID o) };
#define FN_8FLDS(F) M_FIRST_ F M_REST_ F;
#define FN_8CL_DEC(rt, n, a) static rt n(void * _envV, M_ID a) { struct n##_env_t * _env = _envV;
#define FN_8FTYPE(rt, C, a, pn) rt(* C pn)a
#define FN_8CTYPE(rt, n, a, pn) rt(* pn)(void *, M_ID a)
#define FN_8FN_TYPE(F) M_CONC(FN_8GETTYPE_, M_FIRST(M_REST((F))))
#define FN_8GETTYPE_8fn(rt, a, ...) rt(* _fun)a
#define FN_8CLSZ(T, N) T M_CONC(_, N);
#define FN_8ZIPNE(NL, BL, Q) (8FLTNE, ((M_ZIP_W2(FN_8ZIPNE_, NL, BL)), Q))
#define FN_8ZIPNE_(N, B) ,(M_FIRST_ B, N, M_REST_ B)
#define FN_8FLTNE(EL, Q) (8POPEM, ((0 M_FOR_EACH(FN_8FLTNE_, M_ID EL)), Q))
#define FN_8FLTNE_(E) M_IF(M_FIRST_ E, (), (,(M_REST_ E)))
#define FN_8POPEM(FL, Q) M_IF(M_2ORMORE(M_ID FL), ((8F2NS, ((M_REST_ FL), Q))), ((8DO_Q, (Q))))
#define FN_8F2NS(FL, Q) (8DO_Q, ((M_FOR_E2(FN_8F2NS_1, M_ID FL), M_ID Q)))
#define FN_8F2NS_1(F) ,FN_8F2NS_2 F
#define FN_8F2NS_2(n, isC, rt, a, ...) M_IF(isC, \
((8EMIT_NS_NX, (n, (FN_8CL_DEC(rt, n, a)), M_REST(__VA_ARGS__))), (8EMIT_ENV,(n, rt, a, M_FIRST(__VA_ARGS__)))), \
((8EMIT_NS_NX, (n, (static rt n a), __VA_ARGS__))))
#define FN_8DO_Q(Q) (M_ID(M_FIRST_ M_FIRST_ Q),(M_ID M_REST_ M_FIRST_ Q, (M_REST_ Q)))
#define FN_8EMIT_NS_NX(...) (8EMIT_NS, (__VA_ARGS__))
Ммм, дерьмецо
+1
/* Python:
def A004086(n):
return int(str(n)[::-1])
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int A004086(int n) {
char str[12]; // Enough to hold the string representation of an int
sprintf(str, "%d", n);
int len = strlen(str);
char reversed[12];
for (int i = 0; i < len; i++) {
reversed[i] = str[len - 1 - i];
}
reversed[len] = '\0'; // Null-terminate the string
return atoi(reversed);
}
Результат переписывание с "Python" на "C". A004086 это последовательность из OEIS https://oeis.org/A004086
0
/* Windows doesn't support the fork() call; so we fake it by invoking
another copy of Wget with the same arguments with which we were
invoked. The child copy of Wget should perform the same initialization
sequence as the parent; so we should have two processes that are
essentially identical. We create a specially named section object that
allows the child to distinguish itself from the parent and is used to
exchange information between the two processes. We use an event object
for synchronization. */
static void
fake_fork (void)
{
char exe[MAX_PATH + 1];
DWORD exe_len, le;
SECURITY_ATTRIBUTES sa;
HANDLE section, event, h[2];
STARTUPINFO si;
PROCESS_INFORMATION pi;
struct fake_fork_info *info;
char *name;
BOOL rv;
section = pi.hProcess = pi.hThread = NULL;
/* Get the fully qualified name of our executable. This is more reliable
than using argv[0]. */
exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
if (!exe_len || (exe_len >= sizeof (exe)))
return;
sa.nLength = sizeof (sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/* Create an anonymous inheritable event object that starts out
non-signaled. */
event = CreateEvent (&sa, FALSE, FALSE, NULL);
if (!event)
return;
/* Create the child process detached form the current console and in a
suspended state. */
xzero (si);
si.cb = sizeof (si);
rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
CREATE_SUSPENDED | DETACHED_PROCESS,
NULL, NULL, &si, &pi);
if (!rv)
goto cleanup;
/* Create a named section object with a name based on the process id of
the child. */
name = make_section_name (pi.dwProcessId);
section =
CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
sizeof (struct fake_fork_info), name);
le = GetLastError();
xfree (name);
/* Fail if the section object already exists (should not happen). */
if (!section || (le == ERROR_ALREADY_EXISTS))
{
rv = FALSE;
goto cleanup;
}
/* Copy the event handle into the section object. */
info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
if (!info)
{
rv = FALSE;
goto cleanup;
}
info->event = event;
UnmapViewOfFile (info);
/* Start the child process. */
rv = ResumeThread (pi.hThread);
if (!rv)
{
TerminateProcess (pi.hProcess, (DWORD) -1);
goto cleanup;
}
/* Wait for the child to signal to us that it has done its part. If it
terminates before signaling us it's an error. */
h[0] = event;
h[1] = pi.hProcess;
rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
if (!rv)
goto cleanup;
info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
if (!info)
{
rv = FALSE;
goto cleanup;
}
Из исходников wget.
https://git.savannah.gnu.org/cgit/wget.git/tree/src/mswindows.c
0
int IsEven(long long int number){
if (number == 0) return 0;
long long int loc_num = 0;
update:
if (number == loc_num+1) {return 1;
} else if (number == (loc_num+1)*(-1)) { return 1;
} else {
if (number == loc_num+2) {return 0;
} else if (number == (loc_num+2)*(-1)) { return 0;
} else {
if (number == loc_num+3) {return 1;
} else if (number == (loc_num+3)*(-1)) { return 1;
} else {
if (number == loc_num+4) {return 0;
} else if (number == (loc_num+4)*(-1)) { return 0;
} else {
if (number == loc_num+5) {return 1;
} else if (number == (loc_num+5)*(-1)) { return 1;
} else {
if (number == loc_num+6) {return 0;
} else if (number == (loc_num+6)*(-1)) { return 0;
} else {
if (number == loc_num+7) {return 1;
} else if (number == (loc_num+7)*(-1)) { return 1;
} else {
if (number == loc_num+8) {return 0;
} else if (number == (loc_num+8)*(-1)) { return 0;
} else {
if (number == loc_num+9) {return 1;
} else if (number == (loc_num+9)*(-1)) { return 1;
} else {
if (number == loc_num+10) {return 0;
} else if (number == (loc_num+10)*(-1)) { return 0;
} else {
loc_num+=10;
goto update;
}
}
}
}
}
}
}
}
}
}
}