ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Hi, I was wanting to know if it would be worth it to learn a some low level programming(binary, hex, assembly). I am a senior in high school, and I'm wanting to go to college for computer science. So, I figured I would learn all that stuff there, right? I currently program in C/C++, Python, and do some Bash shell scripting. Every time I write a program I can't help but wonder how it all works underneath. With my dual core processor and 2 gigs of memory, it isn't a matter of performance, or hard disk space - its just to learn.
So what do you think?
Do I feed my urges to know how everything works, or is it way over my head and just hold off until college?
Do it if you are passionate about it. And the only way to determine that is to dive in and discover. If you find it dreary, point your brain elsewhere. If you eat, drink, and live low-level programming, you will be in great demand.
Regardless, having a sound understanding of the fundamentals from hardware up through software and higher still to protocols will be very valuable to anything you do in computer science.
Assembler was one of the first languages I learned (I couldn't afford a C compiler).
If you want to be good at computers it's not just a matter of knowing one programming language or other; it's mostly understanding how things work. If you've read about, say, the theory of finite automata then you'd know all the absolute basics including how to decide if something is computable or not. That's all theory though and has absolutely nothing to do with implementations.
The other thing you need to be familiar with are generic algorithms. Once again this has nothing to do with implementations (unless you're talking about how to take advantage of a particular feature of a CPU to improve the calculation time of a certain algorithm).
Somewhat in parallel with learning about algorithms you'll have to get into actual implementations. Now things get messy. Once upon a time we used assembly but since then higher level programming languages have become much more popular. However, it's good to know how things work underneath - even in theory only. One popular example of that would be Donald Knuth's 'MMIX' machine. You can read about it and download 'fascicles' from Don Knuth's website - you'll have to get the fascicles in the correct order though or nothing will make sense. MMIX is an imaginary machine created for teaching purposes. Aside from teaching a little about modern CPU architecture, it is also the machine that you're encouraged to program for as you read through Don Knuth's series The Art of Computer Programming.
If you can borrow TAoCP (one volume at a time!) from a library and read through it, and also look at Don Knuth's latest fascicles for updated information, I think you'll get the best results. You can even install an MMIX emulator and play around with it. I don't know if the original MIX emulators can still be found - they wouldn't be as useful as MMIX; MIX was typical of a microprocessor from around 1968 and is still somewhat useful if you're only interested in 'microcontrollers' which are commonly used in industry, but if you can master MMIX, you'll find microcontrollers are just the same - only much simpler (which can actually be frustrating at times).
...and another aspect that occurred to me after reading pinniped's post. It is not uncommon to have to get dirty with a debugger and crawl through assembler code to debug a problem where you don't have source, or for compiler bugs, or to see how the optimizer optimizes certain code blocks.
You'll most likely discover you're either a high-level or low-level programmer, preferring one to the other. This is just a gross generalization, as of course their are those who enjoy (and perhaps even excel) in both camps.
yes, it would definitely help you to learn some low level programming. welcome to the fold
try searching on Google groups for alt.lang.asm and comp.lang.asm.x86, their archives, not to mention your problems that you might post there, will help you IMMENSELY.
I researched MMIX, sounds interesting. After a bit more "googling" I'll probably download the emulator. I also checked out the user groups resetreset mentioned. Hopefully I'll get the hang of it. I at least know how it works in theory, anyway. Or maybe it will be a big frustrating nightmare.
You definitely need to learn binary and hexadecimal arithmetic no matter what programming languages you learn. Knowing binary is essential for understanding logical operators in any language.
Dumps are printed in hexadecimal regardless of the programming language the source is in. So whenever you have to debug from a dump you have to know hexadecimal arithmetic.
Assembly language is patterned after the hardware logic design. If you are dealing with the hardware up close, such as writing an OS or a device driver, knowing assembly is essential. That is true even if you are writing machine dependent code in C or other high level languages.
On the other hand if you are writing applications code in a high level language then assembly is irrelevant. For example if your program solves calculus problems describing the air flow over an airplane wing then learning assembly is a waste of time.
If you are going to major in computer science then you will encounter enough hardware considerations that knowing assembly will be an advantage to you. Be forewarned that the assembly language is different for each computer architecture so the assembly you learn now might not be the same as the assembly taught by the college you go to. It depends on what computer your college uses to teach assembly.
If programming is something that interests you, and if you could want to make a living as developer, now is the time. It will help you get better than "average" students "usually" and could lead to a good career.
Don't focus on the recommended books for your courses though, buy the best recommended books by "real programmers"(as many as you can afford). In my opinion, books recommended by teachers:
- are not that good, easy to understand for the sake of the course, but teach bad habits or teach badly
- cover all sort of things in the same book which prevent you from having a "clear" general overview of topics relationships.
At job interviews, you can be asked about the programming books you read, and they are probably not expecting any of those that you used for your classes.
Try contributing in a non trivial open source C++ project, time to time(If C++ is a language you think you could work a lot with). It can be tough, but if you manage to learn, understand and contribute some code, then:
- you're probably few levels above the students of your classes
- and maybe above professional programmers with few years of experience.
Knowing more than one language as you do, make sometimes a huge difference:
- as you know other approaches to solve problems
- A language can introduce concepts that are not evoked often in other programming languages
- as you could be competent in a technology migration
- as you would be easily eligible to work on projects written in other programming languages in a company
- Subscribing to programming RSS feeds and visiting programming blogs is a good thing too.
- Trying to write portable code is a good thing, as much as possible
- Writing understandable/readable code is a good thing
I learned to program in assembler for a few different microprocessors and microcontrollers before I ever learned C or other high level languages. In learning C especially, I'm certain that my knowledge of assembler and the basic machine architecture was helpful in understanding the C language. Concepts that are fundamental to C (pointers, for sure. also strings) seemed very natural to me, where others find the concept more abstract and foreign. It made me feel quite comfortable dropping into an disassembled view of code in a debugger. I was able to conceive what the compiled code might look like, and how it might be affected by the way I wrote my high level code. Knowing that ultimately, everything ends up as procedural object code, I think it made me somewhat brain damaged about embracing objected oriented concepts (that's my excuse and I'm sticking with it). If you will ever write code that pokes around at the hardware very much, then having a feel for the methods, tools, and lexicon of the assembly language programmer will give you a leg up. Seeing a value expressed in hex or octal, and making a quick mental picture of the bit patterns and the potential significance of a subset of those bits is a skill used routinely by the bit basher crowd. There are a few online forums and similar groups that engage in the embedded systems field. If you think that the low-level stuff might hold some appeal to you, seek out and lurk in some of those.
I have a few books on Linux and C++, but I mainly prefer the reference books when it comes to programming. I find it way more effective and not so boring when I just download a source code, read through some parts, and look up all the functions or operations I don't understand. Changing stuff and running it probably works the best. I started programming in python then started to get into C/C++. So I kind of went in the opposite direction as theNbomr. The closest I got to hardware was probably doing memory in C. I got interested in low level code when I wrote a binary calculator in C++. After I wrote that I got pretty good at converting decimal to binary, octal, or hex and vise versa. In binary I can do simple arithmetic (ie. +-/*), but the part I don't understand is how it is used in programming. I have searched many times, but all it tells me is the simple arithmetic. Does any body know how or where I can get more info on this?
In binary I can do simple arithmetic (ie. +-/*), but the part I don't understand is how it is used in programming. I have searched many times, but all it tells me is the simple arithmetic. Does any body know how or where I can get more info on this?
The hardware works in binary. People find that doing the arithmetic in hexadecimal is easier than doing it in binary so people usually program thinking in terms of hexadecimal. From a theoretical mathematical viewpoint there is no difference between binary and hexadecimal. You get the same answer either way. The hardware just does it all in binary.
Boolean logic is part of binary arithmetic. In addition to +-/* you need to know AND, OR, EXCLUSIVE OR, NOT, and truth tables. At the hardware level most of the circuitry is Boolean logic. Such things as binary addition are done with Boolean logic circuits. Boolean logic is found in every programming language, for example statements like:
if ( x OR b ) then
Here is a description of Boolian logic that looks to me like it was written for a hardware designer:
If you are going to do multibyte or arbitrary precision arithmetic, you need to understand how the arithmetic instructions and flags work. Not all CPUs or systems contain a floating point arithmetic processor. And not all arithmetic operations performed in the native format of a system will have sufficient precision for all purposes. In any case, the standard mathematical functions provided by a high level language will probably contain a significant amount of code that manipulates data at the bit level. Someone has to write this stuff. A lot of standard operations such as multiplication & division by powers of two are readily performed with the relatively fast shift operator/instruction.
Boolean logic can be used to describe the logic performed in hardware or by software. If it can be done in hardware, it will be many orders of magnitude faster.
The use of hexadecimal, octal, and binary in low-level programming is only a notation of convenience. Since a byte is eight bits, it is very easy to express a single byte as a two hexadecimal digits. The bit pattern of a single hexadecimal digit can be very easily remembered, having only '10' states. A hex digit is also easily converted from the pure binary format to the corresponding ASCII character, which makes it useful for displaying debug-style info on text terminals and other primitive hardware. The reverse transformation is also true, and there is no overlap between digits of a multibyte word. None of these conditions is true when using decimal notation to express the value of even a single byte.
When writing/reading data to/from control-registers of some peripheral chip, the data is often simply a collection of bits organized into a byte or larger word. In order to manipulate the pattern of bits read or written, it is often necessary to apply boolean logic to the data. For example, to clear a bit (say, bit 4 as an example) in a register, one could potentially read the word, logically 'AND' the word with '0xFFEF', and then write the result back to the register. Any number of other boolean operators/instructions may be required either alone or in combination depending on the application.
A handy interface that can exercise your skills in handling data and control registers is the standard PC Parallel interface. It is dead easy to access, very standard (except for the modern USB implementations), well documented, fairly robust, more or less ubiquitous on older (free) hardware. If you get a few LEDs and some wire, you can try your hand at bit bashing with the instant gratification of blinken-lights, and get a feel for how low-level programming is performed.
I am familiar with boolean logic, although, I don't use it very much, but it seems pretty easy.
ASCII- thats what I was looking for. I seen it everywhere I guess I just never payed attention to it. Its all coming pretty clear to me now. I just need to get my hands on it.
theNbomr- What exactly are you talking about when you said "Pc Parallel interface"?. I tried searching for it but the results consisted of so many different things.
The standard way of interfacing to printers used to be with a 'parallel port', that implemented a form of printer interface that was originally used by Centronix brand printers (30 or so years ago). This became somewhat of an industry standard, and was found on virtually all PCs. Usually, there were two or more of these interfaces, and their nature made them natural candidates to interface all manner of other devices: external storage media, security dongles, simple networks, you name it. It employs a few registers for reading and writing TTL level logic that is accessible in very standard ways, both from the internal IO mapping standpoint, as well as the external hardware connection standpoint. Hackers flocked to it as a way of interfacing whatever external doo-dads they cooked up in their basements. There are numerous sites with good documentation of how to use the hardware, and how to write software to access it. I chose it for an interface in a recent project I did at my work for many of the above reasons. Sadly, for some of us, it has all but disappeared from modern use. However, it's ubiquity on older hardware still makes it useful as a training tool or for use as a way to interface special purpose custom hardware.
It has had many common names over the years: "Printer Port", "Parallel port", "Centronix port/interface", "LPT1:, LPT2: etc" all refer to the same thing. Its description as a "parallel port" distinguishes it from the "serial port" by the nature of the data transfer method it uses: 8 parallel bits strobed into (or from in some cases) the external data pins. A "Serial Port", in contrast, uses a single conductor for each of the send & receive path, with bits being transmitted in series over time (one after the other, in a defined timing arrangement).
Hope this helps.