programing tip

어셈블리에서 프로그래밍하는 이유는 무엇입니까?

itbloger 2020. 9. 15. 07:30
반응형

어셈블리에서 프로그래밍하는 이유는 무엇입니까? [닫은]


모든 하드 코어 저수준 해커들에게 질문이 있습니다. 블로그에서이 문장을 보았습니다. 나는 그것이 일반적인 진술처럼 보이기 때문에 출처가 중요하다고 생각하지 않습니다 (정말 관심이 있다면 Haack입니다).

예를 들어, 많은 최신 3D 게임에는 C ++ 및 어셈블리로 작성된 고성능 코어 엔진이 있습니다.

어셈블리가 진행되는 한-컴파일러가 추가 명령을 내보내거나 과도한 바이트를 사용하는 것을 원하지 않거나 C로 표현할 수없는 (또는없이 표현할 수없는) 더 나은 알고리즘을 사용하고 있기 때문에 컴파일러가 그들을 괴롭히는 것)?

저수준의 것들을 이해하는 것이 중요하다는 것을 완전히 이해합니다. 나는 당신이 그것을 이해 한 후에 어셈블리의 프로그램 을 이해하고 싶습니다 .


이 진술을 잘못 읽은 것 같습니다.

예를 들어, 많은 최신 3D 게임에는 C ++ 및 어셈블리로 작성된 고성능 코어 엔진이 있습니다.

게임 (그리고 요즘 대부분의 프로그램)은 "C ++로 작성"하는 것과 같은 방식으로 "어셈블리로 작성"되지 않습니다. 이 블로그는 게임의 상당 부분이 어셈블리로 설계되었거나 프로그래머 팀이 기본 언어로 어셈블리를 개발하고 있다고 말하는 것이 아닙니다.

이것이 실제로 의미하는 바는 개발자가 먼저 게임을 작성하고 C ++에서 작동하게한다는 것입니다. 그런 다음 프로필을 작성하고 병목 현상이 무엇인지 파악하고 가치가있는 경우 어셈블리에서 문제를 최적화합니다. 또는 이미 경험이 있다면 어떤 부분이 병목 현상이 될지 알고 있으며, 자신이 만든 다른 게임에서 최적화 된 부분을 가지고 있습니다.

어셈블리 프로그래밍 요점 은 항상 그랬던 것처럼 속도 입니다. 어셈블러에서 많은 코드 를 작성하는 것은 우스꽝 스러울 것입니다 . 그러나 컴파일러가 인식하지 못하는 최적화가 있으며, 코드 창이 작 으면 사람이 더 잘할 수 있습니다.

예를 들어 부동 소수점의 경우 컴파일러는 상당히 보수적 인 경향이 있으며 아키텍처의 일부 고급 기능을 인식하지 못할 수 있습니다. 오류를 기꺼이 받아들이고 싶다면 일반적으로 컴파일러보다 더 잘할 수 있으며 많은 시간이 소요되는 경우 어셈블리에 약간의 코드를 작성하는 것이 좋습니다.

다음은 좀 더 관련성이 높은 예입니다.

게임의 예

  • SSE 내장 함수를 사용하여 게임 엔진을 최적화하는 방법에 대한 인텔의 기사 . 최종 코드는 인라인 어셈블러가 아닌 내장 함수를 사용하므로 순수 어셈블리의 양이 매우 적습니다. 그러나 그들은 정확히 무엇을 최적화해야하는지 알아 내기 위해 컴파일러의 어셈블러 출력을 살펴 봅니다.

  • Quake의 빠른 역 제곱근 . 다시 말하지만, 루틴에는 어셈블러가 없지만 이런 종류의 최적화를 수행하려면 아키텍처에 대해 알아야합니다. 저자는 어떤 연산이 빠르고 (곱하기, 시프트) 느린 지 (나누기, sqrt) 알고 있습니다. 그래서 그들은 느린 작업을 완전히 피하는 매우 까다로운 제곱근 구현을 제시합니다.

고성능 컴퓨팅

  • 게임 영역 밖에서 과학 컴퓨팅 분야의 사람들은 최신 하드웨어에서 빠르게 실행되도록하기 위해 사물을 최적화하는 경우가 많습니다. 물리학을 속일 수없는 게임이라고 생각하세요.

    이에 대한 최근의 훌륭한 예는 Lattice Quantum Chromodynamics (Lattice QCD) 입니다. 이 백서 에서는 IBM Blue Gene / L 에서 PowerPC 440에 최적화 된 매우 작은 컴퓨팅 커널 하나에 문제가 어떻게 발생하는지 설명합니다 . 각 440에는 두 개의 FPU가 있으며 컴파일러가 악용하기 까다로운 몇 가지 특수 삼항 연산을 지원합니다. 이러한 최적화가 없었다면 Lattice QCD는 훨씬 더 느리게 실행되었을 것입니다. 이는 문제가 값 비싼 컴퓨터에서 수백만 CPU 시간을 요구할 때 비용이 많이 듭니다.

    이것이 왜 중요한지 궁금하다면 이 작업에서 나온 Science기사를 확인하십시오 . Lattice QCD를 사용하여이 사람들은 첫 번째 원리에서 양성자의 질량을 계산했고, 작년에 질량의 90 %가 강한 힘 결합 에너지에서 나오고 나머지는 쿼크에서 나온다는 것을 보여주었습니다. 그건 E = MC 2 행동한다. 요약은 다음과 같습니다 .

위의 모든 경우, 응용 프로그램은되어 있지 설계 또는 어셈블리에 100 %를 기록 - 근처에도 없습니다. 그러나 사람들이 정말로 속도가 필요할 때 그들은 특정 하드웨어에서 날아 가기 위해 코드의 핵심 부분을 작성하는 데 집중합니다.


수년 동안 어셈블리 언어로 코딩하지 않았지만 자주 본 몇 가지 이유를 제시 할 수 있습니다.

  • 모든 컴파일러가 특정 CPU 최적화 및 명령어 세트를 사용할 수있는 것은 아닙니다 (예 : 인텔이 가끔씩 추가하는 새로운 명령어 세트). 컴파일러 작성자가 따라 잡을 때까지 기다리면 경쟁 우위를 잃게됩니다.

  • 실제 코드를 알려진 CPU 아키텍처 및 최적화에보다 쉽게 ​​일치시킬 수 있습니다. 예를 들어, 가져 오기 메커니즘, 캐싱 등에 대해 알고있는 것입니다. 이것은 개발자에게 투명해야하지만 사실은 그렇지 않다는 것입니다. 이것이 컴파일러 작성자가 최적화 할 수있는 이유입니다.

  • 특정 하드웨어 레벨 액세스는 어셈블리 언어를 통해서만 가능 / 실용적입니다 (예 : 장치 드라이버 작성시).

  • 코드의 최종 또는 거의 최종 레이아웃이 무엇인지 이미 알고 있기 때문에 형식적 추론이 고수준 언어보다 어셈블리 언어에서 실제로 더 쉽습니다.

  • Programming certain 3D graphic cards (circa late 1990s) in the absence of APIs was often more practical and efficient in assembly language, and sometimes not possible in other languages. But again, this involved really expert-level games based on the accelerator architecture like manually moving data in and out in certain order.

I doubt many people use assembly language when a higher-level language would do, especially when that language is C. Hand-optimizing large amounts of general-purpose code is impractical.


There is one aspect of assembler programming which others have not mentioned - the feeling of satisfaction you get knowing that every single byte in an application is the result of your own effort, not the compiler's. I wouldn't for a second want to go back to writing whole apps in assembler as I used to do in the early 80s, but I do miss that feeling sometimes...


Usually, a layman's assembly is slower than C (due to C's optimization) but many games (I distinctly remember Doom) had to have specific sections of the game in Assembly so it would run smoothly on normal machines.

Here's the example to which I am referring.


I started professional programming in assembly language in my very first job (80's). For embedded systems the memory demands - RAM and EPROM - were low. You could write tight code that was easy on resources.

By the late 80's I had switched to C. The code was easier to write, debug and maintain. Very small snippets of code were written in assembler - for me it was when I was writing the context switching in an roll-your-own RTOS. (Something you shouldn't do anymore unless it is a "science project".)

You will see assembler snippets in some Linux kernel code. Most recently I've browsed it in spinlocks and other synchronization code. These pieces of code need to gain access to atomic test-and-set operations, manipulating caches, etc.

I think you would be hard pressed to out-optimize modern C compilers for most general programming.

I agree with @altCognito that your time is probably better spent thinking harder about the problem and doing things better. For some reason programmers often focus on micro-efficiencies and neglect the macro-efficiencies. Assembly language to improve performance is a micro-efficiency. Stepping back for a wider view of the system can expose the macro problems in a system. Solving the macro problems can often yield better performance gains. Once the macro problems are solved then collapse to the micro level.

I guess micro problems are within the control of a single programmer and in a smaller domain. Altering behavior at the macro level requires communication with more people - a thing some programmers avoid. That whole cowboy vs the team thing.


"Yes". But, understand that for the most part the benefits of writing code in assembler are not worth the effort. The return received for writing it in assembly tends to be smaller than the simply focusing on thinking harder about the problem and spending your time thinking of a better way of doing thigns.

John Carmack and Michael Abrash who were largely responsible for writing Quake and all of the high performance code that went into IDs gaming engines go into this in length detail in this book.

I would also agree with Ólafur Waage that today, compilers are pretty smart and often employ many techniques which take advantage of hidden architectural boosts.


These days, for sequential codes at least, a decent compiler almost always beats even a highly seasoned assembly-language programmer. But for vector codes it's another story. Widely deployed compilers don't do such a great job exploiting the vector-parallel capabilities of the x86 SSE unit, for example. I'm a compiler writer, and exploiting SSE tops my list of reasons to go on your own instead of trusting the compiler.


SSE code works better in assembly than compiler intrinsics, at least in MSVC. (i.e. does not create extra copies of data )


Some instructions/flags/control simply aren't there at the C level.

For example, checking for overflow on x86 is the simple overflow flag. This option is not available in C.


Defects tend to run per-line (statement, code point, etc.); while it's true that for most problems, assembly would use far more lines than higher level languages, there are occasionally cases where it's the best (most concise, fewest lines) map to the problem at hand. Most of these cases involve the usual suspects, such as drivers and bit-banging in embedded systems.


I've three or four assembler routines (in about 20 MB source) in my sources at work. All of them are SSE(2), and are related to operations on (fairly large - think 2400x2048 and bigger) images.

For hobby, I work on a compiler, and there you have more assembler. Runtime libraries are quite often full of them, most of them have to do with stuff that defies the normal procedural regime (like helpers for exceptions etc.)

I don't have any assembler for my microcontroller. Most modern microcontrollers have so much peripheral hardware (interrupt controled counters, even entire quadrature encoders and serial building blocks) that using assembler to optimize the loops is often not needed anymore. With current flash prices, the same goes for code memory. Also there are often ranges of pin-compatible devices, so upscaling if you systematically run out of cpu power or flash space is often not a problem

Unless you really ship 100000 devices and programming assembler makes it possible to really make major savings by just fitting in a flash chip a category smaller. But I'm not in that category.

A lot of people think embedded is an excuse for assembler, but their controllers have more CPU power than the machines Unix was developed on. (Microchip coming with 40 and 60 MIPS microcontrollers for under USD 10).

However a lot people are stuck with legacy, since changing microchip architecture is not easy. Also the HLL code is very architecture dependent (because it uses the hardware periphery, registers to control I/O, etc). So there are sometimes good reasons to keep maintaining a project in assembler (I was lucky to be able to setup affairs on a new architecture from scratch). But often people kid themselves that they really need the assembler.

I still like the answer a professor gave when we asked if we could use GOTO (but you could read that as ASSEMBLER too): "if you think it is worth writing a 3 page essay on why you need the feature, you can use it. Please submit the essay with your results. "

I've used that as a guiding principle for lowlevel features. Don't be too cramped to use it, but make sure you motivate it properly. Even throw up an artificial barrier or two (like the essay) to avoid convoluted reasoning as justification.


Another reason could be when the available compiler just isn't good enough for an architecture and the amount of code needed in the program is not that long or complex as for the programmer to get lost in it. Try programming a microcontroller for an embedded system, usually assembly will be much easier.


Beside other mentioned things, all higher languages have certain limitations. Thats why some people choose to programm in ASM, to have full control over their code.

Others enjoy very small executables, in the range of 20-60KB, for instance check HiEditor, which is implemented by author of the HiEdit control, superb powerfull edit control for Windows with syntax highlighting and tabs in only ~50kb). In my collection I have more then 20 such gold controls from Excell like ssheets to html renders.


I think a lot of game developers would be surprised at this bit of information.

Most games I know of use as little assembly as at all possible. In some cases none at all, and at worst, one or two loops or functions.

That quote is over-generalized, and nowhere near as true as it was a decade ago.

But hey, mere facts shouldn't hinder a true hacker's crusade in favor of assembly. ;)


If you are programming a low end 8 bit microcontroller with 128 bytes of RAM and 4K of program memory you don't have much choice about using assembly. Sometimes though when using a more powerful microcontroller you need a certain action to take place at an exact time. Assembly language comes in useful then as you can count the instructions and so measure the clock cycles used by your code.


If you were around for all the Y2K remediation efforts, you could have made a lot of money if you knew Assembly. There's still plenty of legacy code around that was written in it, and that code occasionally needs maintenance.


Aside from very small projects on very small CPUs, I would not set out to ever program an entire project in assembly. However, it is common to find that a performance bottleneck can be relieved with the strategic hand coding of some inner loops.

In some cases, all that is really required is to replace some language construct with an instruction that the optimizer cannot be expected to figure out how to use. A typical example is in DSP applications where vector operations and multiply-accumulate operations are difficult for an optimizer to discover, but easy to hand code.

For example certain models of the SH4 contain 4x4 matrix and 4 vector instructions. I saw a huge performance improvement in a color correction algorithm by replacing equivalent C operations on a 3x3 matrix with the appropriate instructions, at the tiny cost of enlarging the correction matrix to 4x4 to match the hardware assumption. That was achieved by writing no more than a dozen lines of assembly, and carrying matching adjustments to the related data types and storage into a handful of places in the surrounding C code.


It doesn't seem to be mentioned, so I thought I'd add it: in modern games development, I think at least some of the assembly being written isn't for the CPU at all. It's for the GPU, in the form of shader programs.

This might be needed for all sorts of reasons, sometimes simply because whatever higher-level shading language used doesn't allow the exact operation to be expressed in the exact number of instructions wanted, to fit some size-constraint, speed, or any combination. Just as usual with assembly-language programming, I guess.


Almost every medium-to-large game engine or library I've seen to date has some hand-optimized assembly versions available for matrix operations like 4x4 matrix concatenation. It seems that compilers inevitably miss some of the clever optimizations (reusing registers, unrolling loops in a maximally efficient way, taking advantage of machine-specific instructions, etc) when working with large matrices. These matrix manipulation functions are almost always "hotspots" on the profile, too.

I've also seen hand-coded assembly used a lot for custom dispatch -- things like FastDelegate, but compiler and machine specific.

Finally, if you have Interrupt Service Routines, asm can make all the difference in the world -- there are certain operations you just don't want occurring under interrupt, and you want your interrupt handlers to "get in and get out fast"... you know almost exactly what's going to happen in your ISR if it's in asm, and it encourages you to keep the bloody things short (which is good practice anyway).


Games are pretty performance hungry and although in the meantime the optimizers are pretty good a "master programmer" is still able to squeeze out some more performance by hand coding the right parts in assembly.

Never ever start optimizing your program without profiling it first. After profiling should be able to identify bottlenecks and if finding better algorithms and the like don't cut it anymore you can try to hand code some stuff in assembly.


I have only personally talked to one developer about his use of assembly. He was working on the firmware that dealt with the controls for a portable mp3 player. Doing the work in assembly had 2 purposes:

  1. Speed: delays needed to be minimal.
  2. Cost: by being minimal with the code, the hardware needed to run it could be slightly less powerful. When mass-producing millions of units, this can add up.

The only assembler coding I continue to do is for embedded hardware with scant resources. As leander mentions, assembly is still well suited to ISRs where the code needs to be fast and well understood.

A secondary reason for me is to keep my knowledge of assembly functional. Being able to examine and understand the steps which the CPU is taking to do my bidding just feels good.


Last time I wrote in assembler was when I could not convince the compiler to generate libc-free, position independent code.

Next time will probably be for the same reason.

Of course, I used to have other reasons.


A lot of people love to denigrate assembly language because they've never learned to code with it and have only vaguely encountered it and it has left them either aghast or somewhat intimidated. True talented programmers will understand that it is senseless to bash C or Assembly because they are complimentary. in fact the advantage of one is the disadvantage of the other. The organized syntaxic rules of C improves clarity but at the same gives up all the power assembly has from being free of any structural rules ! C code instruction are made to create non-blocking code which could be argued forces clarity of programming intent but this is a power loss. In C the compiler will not allow a jump inside an if/elseif/else/end. Or you are not allowed to write two for/end loops on diferent variables that overlap each other, you cannot write self modifying code (or cannot in an seamless easy way), etc.. conventional programmers are spooked by the above, and would have no idea how to even use the power of these approaches as they have been raised to follow conventional rules. Here is the truth : Today we have machine with the computing power to do much more that the application we use them for but the human brain is too incapable to code them in a rule free coding environment (= assembly) and needs restrictive rules that greatly reduce the spectrum and simplifies coding. I have myself written code that cannot be written in C code without becoming hugely inefficient because of the above mentionned limitations. And i have not yet talked about speed which most people think is the main reason for writting in assembly, well it is if you mind is limited to thinking in C then you are the slave of you compiler forever. I always thought chess players masters would be ideal assembly programmers while the C programmers just play "Dames".


No longer speed, but Control. Speed will sometimes come from control, but it is the only reason to code in assembly. Every other reason boils down to control (i.e. SSE and other hand optimization, device drivers and device dependent code, etc.).


If I am able to outperform GCC and Visual C++ 2008 (known also as Visual C++ 9.0) then people will be interested in interviewing me about how it is possible.

This is why for the moment I just read things in assembly and just write __asm int 3 when required.

I hope this help...


I've not written in assembly for a few years, but the two reasons I used to were:

  • The challenge of the thing! I went through a several-month period years ago when I'd write everything in x86 assembly (the days of DOS and Windows 3.1). It basically taught me a chunk of low level operations, hardware I/O, etc.
  • For some things it kept size small (again DOS and Windows 3.1 when writing TSRs)

I keep looking at coding assembly again, and it's nothing more than the challenge and joy of the thing. I have no other reason to do so :-)


I once took over a DSP project which the previous programmer had written mostly in assembly code, except for the tone-detection logic which had been written in C, using floating-point (on a fixed-point DSP!). The tone detection logic ran at about 1/20 of real time.

I ended up rewriting almost everything from scratch. Almost everything was in C except for some small interrupt handlers and a few dozen lines of code related to interrupt handling and low-level frequency detection, which runs more than 100x as fast as the old code.

An important thing to bear in mind, I think, is that in many cases, there will be much greater opportunities for speed enhancement with small routines than large ones, especially if hand-written assembler can fit everything in registers but a compiler wouldn't quite manage. If a loop is large enough that it can't keep everything in registers anyway, there's far less opportunity for improvement.


The Dalvik VM that interprets the bytecode for Java applications on Android phones uses assembler for the dispatcher. This movie (about 31 minutes in, but its worth watching the whole movie!) explains how

"there are still cases where a human can do better than a compiler".


I don't, but I've made it a point to at least try, and try hard at some point in the furture (soon hopefully). It can't be a bad thing to get to know more of the low level stuff and how things work behind the scenes when I'm programming in a high level language. Unfortunately time is hard to come by with a full time job as a developer/consultant and a parent. But I will give at go in due time, that's for sure.

참고URL : https://stackoverflow.com/questions/791533/why-do-you-program-in-assembly

반응형