| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#121
| |||
| |||
| On Aug 2, 12:25 am, Jerry Avins <j...@ieee.org> wrote: > Chip Eastham wrote: > > On Aug 1, 2:10 pm, hru...@odds.stat.purdue.edu (Herman Rubin) wrote: > > >> In article <zaCdnQMdrPKvjS3bnZ2dnUVZ_snin...@comcast.com>, > >> glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote: > > >>> To me the problem with doing inline assembly is that > >>> you don't know which registers the compiler is already > >>> using. For the 8080 that doesn't matter much because > >>> it doesn't have enough registers for any to be in > >>> use, but for many processors it does. > > >> One should be able to communicate with the compiler, and > >> to give it directions. Also, one should be able to use > >> variable registers, and there are things which compilers > >> seem unwilling or unable to know. > > > I think a common strategy is to push the contents > > of some or all registers onto the stack as the > > very first step in an inline assembly snippet. > > One then pops these values back into the same > > registers when the inline assembly code ends. > > What a waste of time! With a compiler like that, > I would edit the assembly output to remove the > pushes and pops of the registers my assembly > doesn't use. With the Forths I use, I know which > registers the kernel uses and just avoid them. Hi, Jerry: One can check the .asm output from the C/C++ compiler and determine what registers are available at the point where you wish to inline some handcoded assembly language. I used to do this with Borland's Turbo C/C++ compiler about fifteen years ago, and indeed one becomes familiar with which registers are typically "in use" by application code that the compiler generates. Between lines of C code, in particular, the compiler often moves results to memory from registers, so that apart from the stack pointer and instruction pointer, many of the CPU registers are lying fallow. PUSH/POP is relevant to the case when more registers are needed/wanted in your handcoded assembly than the compiler left available. regards, chip |
|
#122
| |||
| |||
| Randy Yates wrote: (snip) > I see no end to this debate, and I see no fruit in attempting to > communicate the multiple issues that come up in my mind when I read > the statements you and others make on this issue. > However, know this with certainty: Nothing that has been stated here, > by you or anyone else, has changed reality, and that reality is that I > can write code in assembly that consistently, over multiple compiler > vendors, platforms, processors, and software development epochs (the > 70's, 80's, 90's, etc.), that beats the pants off a compiler. But you have to rewrite it for each platform, processor, and even processor version. SPARC assembly doesn't run very well on IA32, and 8088 assembler is less than optimal on a P4, reasonably likely less optimal than a C compiler optimized for P4. For RISC processors it is even more sensitive to the processor level, as the compiler (or assembly programmer) is expected to choose the optimal sequence for that specific processor. Notice how fast Linux is ported to a new machine? How long would it take if written in assembly? (As OS used to be.) -- glen |
|
#123
| |||
| |||
| Androcles wrote: (snip) > When I wrote code I always included "close" with every "open" before > I wrote the code in between. Same with "malloc" (memory allocation) > and "free". If I don't remember to do it at the time then I'm likely > to forget later, the program runs just fine for a while in the testing stage > and then crashes when it's passed to a customer with embarrassing > consequences. I believe both C and Fortran require the system to close files when the program ends. Java does not do that, so one must be sure to close them (to get the last buffer out). All protected mode OS must release a program's memory when it is finished, but coding the free() allows on to use it as a subroutine even if originally written as a main program. Do you always check that the close() succeeds? -- glen |
|
#124
| |||
| |||
| glen herrmannsfeldt <gah@ugcs.caltech.edu> writes: > Randy Yates wrote: > (snip) > >> I see no end to this debate, and I see no fruit in attempting to >> communicate the multiple issues that come up in my mind when I read >> the statements you and others make on this issue. > >> However, know this with certainty: Nothing that has been stated here, >> by you or anyone else, has changed reality, and that reality is that I >> can write code in assembly that consistently, over multiple compiler >> vendors, platforms, processors, and software development epochs (the >> 70's, 80's, 90's, etc.), that beats the pants off a compiler. > > But you have to rewrite it for each platform, processor, and even > processor version. SPARC assembly doesn't run very well on IA32, > and 8088 assembler is less than optimal on a P4, reasonably likely > less optimal than a C compiler optimized for P4. > > For RISC processors it is even more sensitive to the processor > level, as the compiler (or assembly programmer) is expected to choose > the optimal sequence for that specific processor. > > Notice how fast Linux is ported to a new machine? > > How long would it take if written in assembly? (As OS used to be.) Did I say I one should write an entire OS in assembly? No. I am merely stating that, in the special cases where performance or power-savings is at a high premium, the drop to assembly is justified. In such cases there is usually only one processor involved anyway, and if it was changed some years down the road, then yes, it's time to rewrite whatever was in assembly. That's life in the performance lane. ![]() -- % Randy Yates % "Remember the good old 1980's, when %% Fuquay-Varina, NC % things were so uncomplicated?" %%% 919-577-9882 % 'Ticket To The Moon' %%%% <yates@ieee.org> % *Time*, Electric Light Orchestra http://home.earthlink.net/~yatescr |
|
#125
| |||
| |||
| "glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message news:546dnQpzRKak4i_bnZ2dnUVZ_jydnZ2d@comcast.com. .. : Androcles wrote: : (snip) : : > When I wrote code I always included "close" with every "open" before : > I wrote the code in between. Same with "malloc" (memory allocation) : > and "free". If I don't remember to do it at the time then I'm likely : > to forget later, the program runs just fine for a while in the testing stage : > and then crashes when it's passed to a customer with embarrassing : > consequences. : : I believe both C and Fortran require the system to close files : when the program ends. Java does not do that, so one must be : sure to close them (to get the last buffer out). Exception handling by the operating system is called a "crash". http://tinyurl.com/23q3aq : : All protected mode OS must release a program's memory when it : is finished, but coding the free() allows on to use it as a : subroutine even if originally written as a main program. Not all routines are designed to "finish", some only terminate when data is exhausted. Constructing trees is an example. Try programming tic-tac-toe but let the machine "learn" to play. The rules you can hard-code, the objective is for the machine to win or draw by learning the *strategy* of the game just as a small child would, allowing "silly" moves until it is seen that they lead to a loss. Then when you have experience, upgrade to chess. If the program doesn't recognise a stalemate it will never terminate, because unlike tic-tac-toe which must terminate when the board is filled, in chess the board is never filled. It must therefore record all previous states of the board and not repeat them more than three times. Routines that call themselves (recursive routines) are particularly susceptable to sloppy programming. : Do you always check that the close() succeeds? It can't if I don't have one, and the answer is it might depend on my routine (especially if recursive), therefore I always do. As I said, I always pair an open() with a close() before I write the body of the routine in between. As with most programmers I re-use old code (it saves typing) and I often use tried-and-tested text book examples that I modify. I do it like that because I don't want to have to think about it later and can concentrate on what I'm really trying to do. This I might copy and modify, replacing the constant "10" with a variable (otherwise there is not much point to using it anyway): int *ptr = malloc(10 * sizeof (int)); if (ptr == NULL) { /* Memory could not be allocated, so print an error and exit. */ fprintf(stderr, "Couldn't allocate memory\n"); exit(EXIT_FAILURE); } but I also need a free(ptr) BEFORE I modify it or I'll forget. Leaving it out and relying on the OS is just plain sloppy and bad practice. I've seen it done too often as a QA manager, where memory has been allocated and not freed. Everything works fine for hours until you run out of memory. I've even seen a BASIC interpreter that allowed a RETURN without a GOSUB, blowing away the top of the stack. It's not easy to debug when the application programmer did something the systems programmer wasn't expecting him to do and the "it's not my fault" syndrome takes over, each blaming the other and tempers start to fly. True the applications programmer made an error but the systems programmer should have caught it, he gets paid the bigger bucks. When the application programmer is buying, the customer is always right or sales will plummet. As QA, I work for the customer but I'm paid by the company. That's why QA managers report directly to the CEO. Don't be a sloppy programmer or your reputation will suffer. |
|
#126
| |||
| |||
| On Aug 1, 2:39 am, "zzbun...@netscape.net" <zzbun...@netscape.net> wrote: > On Jul 28, 10:18 am, Randy Yates <ya...@ieee.org> wrote: > > > There may come a day when a compiled language can consistently beat a > > good assembly programmer, but that language will never be C. It will > > be a new language that has a radically new, high level way of specifying the > > algorithm to thecompiler, and that has complete control over the generated > > code, including data structures. > > Well, that's not what C was invented for. > It was invented to out-perform thecompilermorons at IBM. > And it has done fabulous. Since the only thing assemblers > have to do with dynamic memory allocation is > George Bush and Intel morons. Or for the Quantum Qranks, we sometimes like to state it as: "NOT ALL OUR PROGRAMS RUN IN REAL NUMBER TIME. SOME OF THEM RUN IN NEGATIVE REAL NUMBER TIME". > > > > > > > To make my point, take a simple example. > > > Consider a fictitious processor that has an architecture with an indirect > > addressing mode. That is, the address can be loaded in a register, and > > that register be used to generate the address for data used in other instructions. > > > Now let's also posit that the processor can post-increment-by-one the > > address registers used for indirect mode for free, but post-increment > > by-two (or other higher values) is not free - i.e., it cost more > > cycles. > > > Now let's say the algorithm to be coded is to sum the real and imaginary > > parts of a complex array. > > > Our programmer, being ignorant of the processor architecture details, > > writes the following code: > > > typedef struct > > { > > int16_t real; > > int16_t imag; > > > } COMPLEX_T; > > > #define N 1024; > > > COMPLEX_T data[N]; > > > COMPLEX_T MyAlgorithm(void) > > { > > uint32_t n; > > COMPLEX_T sum; > > > sum.real = 0; > > sum.imag = 0; > > for (n = 0; n < N; n++) > > { > > sum.real += data[n].real; > > sum.imag += data[n].imag; > > } > > > return sum; > > > } > > > Well, this is not optimized! Never can be, because C can't restructure > > the "data[]" array to put the real and imaginary parts into individual, > > continuous arrays. > > > Also note that if the programmer were to realize this is a problem and > > manually reorganize the data structure, then the resulting code > > becomes SPECIFIC TO THE PROCESSOR. Targeting the code for another > > processor using this new data structure may not be optimal. > > > Also note that requiring the programmer to know the processor architecture > > defeats, at least in part, the point of a high-level-language since time > > is spent learning things that ideally would be handled by thecompiler. > > > Note that this is absolutely irrefutable. The C language (and every other > > computer language that I know of) is not capable of optimizing this BECAUSE > > IT DOESN'T HAVE CONTROL OVER DATA ALIGNMENT AND STRUCTURE. > > -- > > % Randy Yates % "She tells me that she likes me very much, > > %% Fuquay-Varina, NC % but when I try to touch, she makes it > > %%% 919-577-9882 % all too clear." > > %%%% <ya...@ieee.org> % 'Yours Truly, 2095', *Time*, ELO http://home.earthlink.net/~yatescr- Hide quoted text - > > - Show quoted text - |
|
#127
| |||
| |||
| zzbunker@netscape.net wrote: (snip) > Or for the Quantum Qranks, we sometimes like to state it as: > "NOT ALL OUR PROGRAMS RUN IN REAL NUMBER TIME. > SOME OF THEM RUN IN NEGATIVE REAL NUMBER TIME". I would have thought imaginary time for Quantum Qranks, or maybe negative imaginary time. -- glen |
|
#128
| |||
| |||
| On Aug 4, 2:13 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote: > zzbun...@netscape.net wrote: > > (snip) > > > Or for the Quantum Qranks, we sometimes like to state it as: > > "NOT ALL OUR PROGRAMS RUN IN REAL NUMBER TIME. > > SOME OF THEM RUN IN NEGATIVE REAL NUMBER TIME". > > I would have thought imaginary time for Quantum Qranks, > or maybe negative imaginary time. Well, imaginary time is only different from real time in the way i's are different from j's, and k's so that doesn't work except in Hankel Junctions. And negative imaginary time is an option in the axiom of choice, so that only works in neural.nets.philosophy.com. > > -- glen |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.